一、概述
对于ECP5的RISC-V移植采用了PulseRain Reindeer设计。PulseRain Reindeer是冯·诺依曼架构的软CPU。它支持RISC-V RV32I[M]指令集,并具有2 x 2流水线。它在速度和面积之间取得平衡,并为所有FPGA平台上的软CPU提供了灵活的选择。
亮点2x2流水线
PulseRain Reindeer的流水线由4个阶段组成:
- 指令提取(Instruction Fetch)
- 指令解码(Instruction Decode)
- 指令执行(Instruction Execution)
- 寄存器回写和内存访问(Reg and Mem access)
但是,与传统流水线不同,PulseRain Reindeer的流水线映射到 2 x 2 布局,如下Scheme-it绘制的框图所示:
在 2 x 2 布局中,每个级每隔一个时钟周期处于活动状态。对于偶数周期,只有Instruction Fetch和Instruction Execution阶段处于活动状态,而对于奇数周期,只有Instruction Decode和Reg and Mem access阶段处于活动状态。这样,指令提取和内存访问总是发生在不同的时钟周期上,从而避免了单端口存储器造成的结构危险。
亮点 保持和加载
引导软 CPU 往往令人头疼。传统方法或多或少类似于以下内容:
- 在软件中制作引导加载程序
- 将引导加载程序存储在 ROM 中
- 开机复位后,引导加载程序应该首先执行,为此它将其余代码/数据移动到RAM中。之后,PC将设置为新映像的_start地址。
上述方法的缺点是:
- 引导加载程序或多或少会侵入性,因为它占用内存空间。
- ROM 的实现在所有 FPGA 平台上并不一致。对于某些 FPGA,如英特尔 Cyclone 或 Xilinx Artix,存储器初始数据可以存储在 FPGA 比特流中,但其他平台可能会选择使用外部闪存来存储 ROM 数据。引导加载程序本身可以就地执行,也可以加载一个在FPGA结构中实现的小型预加载器。当涉及到SoC + FPGA时,就像Microsemi Smartfusion2一样,硬核处理器也可能参与引导加载。换句话说,软CPU可能需要对应更改才能在各种平台上工作。
为了打破现状,PulseRain Reindeer采用了一种称为“保持和加载”的不同方法,该方法将基于硬件的OCD(片上调试器)带到了前台,如下图所示:
软 CPU 和 OCD 可以共享同一个 UART 端口,如上图所示。RX 信号同时进入软 CPU 和 OCD,而 TX 信号必须通过多路复用器。而那个多路复用器是由强制控制的。
重置后,软CPU将进入保持状态,默认情况下可以访问UART TX端口。但是从主机PC发送的有效调试帧可以让OCD重新配置多路复用器并将UART TX切换到OCD端,可以访问内存,并且可以交换控制。在 CPU 保持状态期间,可以将新的软件映像加载到内存中,这会产生“保持和加载”的名称。
在内存加载新映像后,OCD可以设置软CPU的起始地址,并发送启动脉冲使软CPU处于活动状态。此时,OCD可以将UART TX切换回CPU端以进行CPU输出。
由于保持和加载从外部主机获取软件映像,因此它不需要任何 ROM。这使得它在所有FPGA平台上的可移植性更高。如果使用闪存来存储软件映像,则可以稍微修改OCD,以便从闪存而不是外部主机读取。
二、使用比特流对硬件进行编程
本次设计采用了Reindeer_MachXO3D的工程,将工程文件中MachXO3D的IP核、存储以及管脚等对应替换为ECP5。
Reindeer_MachXO3D的github工程文件:PulseRain/Reindeer_MachXO3D:Port Reindeer to Lattice MachXO3D 分线板 (github.com)
克隆 GitHub 存储库
$ git clone https://github.com/PulseRain/Reindeer_MachXO3D.git
$ cd Reindeer_MachXO3D
$ git submodule update --init --recursive
移植工程
1、通过Reindeer_MachXO3D\build\lattice\MachXO3D_Breakout目录下的MachXO3D.ldf打开Lattice Diamond工程。
2、打开project->Device。
3、将配置改为如下图所示。
4、根据ECP5 MINI板更改对应的IP核。例如将MachXO3D的PLL改为ECP5的PLL,并将时钟输入改为16MHZ。如下图所示:
5、更改完对应的IP核后,编译工程。
6、将所有报错和IP核更改完成后,出现completed successfully表示成功。
7、打开Tools->Spreadsheet View。
8、根据ECP5 MINI的原理图配置对应的引脚,如下图所示。
9、然后依次编译工程剩下的部分,直到所有部分都打上绿色的√。
10、打开Tools->Programmer。
11、配置programmer。
12、点击Program进行烧写。
三、在软 CPU 上运行软件
如上图所示,提供了一个名为reindeer_config.py的python脚本,用于将软件(.elf文件)加载到软CPU中并执行。此时,此脚本仅在 Windows 平台上进行测试。在使用此脚本之前,应执行以下操作以在 Windows 上设置环境:
-
在Windows上安装RISC-V工具链
建议使用 the RISC-V Embedded GCC,它的 v7.2.0-1-20171109 release 可以从这里下载
-
安装后,将RISC-V工具链添加到系统的$PATH
如果使用默认安装路径,则很可能需要将以下路径添加到系统$PATH:
C:\Program Files\GNU MCU Eclipse\RISC-V Embedded GCC\7.2.0-1-20171109-1926\bin
-
在 Windows 上安装 python3
最新的 python for Windows 可以从 https://www.python.org/downloads/windows/ 下载
-
安装完成后,将python二进制和pip3二进制添加到系统的$PATH
例如,如果用户 XYZ 在默认路径中安装了 python 3.7.1,则可能会将以下两个文件夹添加到$PATH:
C:\Users\XYZ\AppData\Local\Programs\Python\Python37 C:\Users\XYZ\AppData\Local\Programs\Python\Python37\Scripts
-
打开命令提示符(您可能需要以管理员身份运行),然后安装 python 的 pyserial 包:
pip3 install pyserial
-
克隆PulseRain Reindeer软 CPU 的 GitHub 存储库
git clone https://github.com/PulseRain/Reindeer.git
-
cd Reindeer/scripts ,然后输入“python reindeer_config.py -h”寻求帮助。有效的命令行选项是
-r, --reset : reset the CPU
-P, --port= : the name of the COM port, such as COM7
-d, --baud= : the baud rate, default to be 115200
-t, --toolchain= : setup the toolchain. By default, riscv-none-embed- is used
-e, --elf= : path and name to the elf image file
-d, --dump_addr : start address for memory dumping
-l, --dump_length : length of the memory dump
-c, --console_enable : switch to observe the CPU UART after image is loaded.
执行以下操作以在 Windows 上烧写程序:
-
将硬件板连接到主机 PC。
-
在使用 python 脚本之前,请确保使用正确的比特流对电路板进行编程。
如果电路板首次使用比特流编程,请拔下并重新插入 USB 电缆,以确保电路板已正确重新初始化。
-
硬件正确连接到主机 PC 后,打开设备管理器以确定硬件使用的 COM 端口。
-
假设硬件使用 COM9,假设用户想要运行 zephyr hello_world,可以使用以下命令:
python reindeer_config.py --port=COM9 --reset --elf=C:\GitHub\Reindeer\bitstream_and_binary\zephyr\hello_world.elf --console_enable --run
如果一切正确,屏幕输出应如下所示:
==============================================================================
# Copyright (c) 2018, PulseRain Technology LLC
# Reindeer Configuration Utility, Version 1.0
==============================================================================
baud_rate = 115200
com_port = COM9
toolchain = riscv-none-embed-
==============================================================================
Reseting CPU ...
Loading C:\GitHub\Reindeer\bitstream_and_binary\zephyr\hello_world.elf
__start 80000000
//================================================================
//== Section vector
//================================================================
addr = 0x80000000, length = 1044 (0x414)
//================================================================
//== Section reset
//================================================================
addr = 0x80004000, length = 4 (0x4)
//================================================================
//== Section exceptions
//================================================================
addr = 0x80004004, length = 620 (0x26c)
//================================================================
//== Section text
//================================================================
addr = 0x80004270, length = 7172 (0x1c04)
//================================================================
//== Section devconfig
//================================================================
addr = 0x80005e74, length = 36 (0x24)
//================================================================
//== Section rodata
//================================================================
addr = 0x80005e98, length = 1216 (0x4c0)
//================================================================
//== Section datas
//================================================================
addr = 0x80006358, length = 28 (0x1c)
//================================================================
//== Section initlevel
//================================================================
addr = 0x80006374, length = 36 (0x24)
===================> start the CPU, entry point = 0x80000000
***** Booting Zephyr OS zephyr-v1.13.0-2-gefde7b1e4a *****
Hello World! riscv32
四、Arduino IDE配置
1、安装 Arudino IDE。版本为1.8.9,对于Windows 10,也可以通过Microsoft商店安装。
2、启动 Arudino IDE。在“File / Preferences”中,将“ Additional Boards Manager URLs”设置为“https://raw.githubusercontent.com/PulseRain/Arduino_RISCV_IDE/master/package_pulserain.com_index.json”,如下所示:
3、在菜单Tools/ Boards / Boards Manager...中,搜索Reindder,然后安装PulseRain Reindeer 1.3.7或更高版本,如下所示:
4、安装主板包后,选择菜单中 Boards / PulseRain RISC-V (Reindeer)/MachXO3D Breakout。
5、插入开发板后,配置串口Tools / Port acoordingly。
6、现在就可以随意进行编程了。
五、展示
当ECP5 MINI核心板通电后,USER指示灯亮起。
按下复位键后,四个RGB灯显绿色常亮一段时间。
RGB灯短暂常亮后,8个RGB灯进行流水。
串口数据打印
将ECP5 MINI核心板设定的串口引脚接到USB-TTL上,打开电脑串口会循环打印以下的信息。以下信息会根据按键引脚高低电平的变化而改变。
六、其他配置
UART 配置
UART应配置为115200波特率,8位数据,无奇偶校验,1停止位
软 CPU 的配置
默认情况下, PulseRain软CPU仅支持RV32I。要使其支持硬件 mul/div (RV32IM),请在 config.h 中将“定义ENABLE_HW_MUL_DIV”转换为 1,然后重建以生成新的比特流。
七、参考资料
ECP5核心板资料:基于ECP5 FPGA的核心板 - 电子森林 (eetree.cn)
RISC-V指令集资料:riscv-spec-20191213.pdf
tinyriscv参考资料(简单、易懂的RISC-V处理器设计):从零开始写RISC-V处理器 | liangkangnan的博客 (gitee.io)
PulseRain Reindeer - RISCV RV32I[M] Soft CPU:PulseRain/Reindeer: PulseRain Reindeer - RISCV RV32I[M] Soft CPU (github.com)