RiscV实现教程
参考来源
tinyriscv: https://gitee.com/liangkangnan/tinyriscv
平台实现 : Linux ubuntu 实现介绍
环境 : 需要 iverilog (切换到 v11或以上的版本)
1.下载iverilog源码
git clone https://github.com/steveicarus/iverilog.git
2.切换到v11分支(必须用V11或以上的版本)
git checkout v11-branch
3.安装依赖
sudo apt-get install autoconf gperf flex bison build-essential
4.编译、安装iverilog和vvp
sh autoconf.sh
./configure
make
make i
nstall
5.创建python软链接
sudo ln -s /usr/bin/python3.8 /usr/bin/python
其中/usr/bin/python3.8对应你实际安装的python版本。
这是大概的环境实现教程 我记得在 python 软连接上面需要注意 ,我pyhton下载的有 2 3 版本,但是内部链接的是2 所以 需要先进入 管理员模式把 python 2 的软连接删除再进行 重新链接新的3系列软连接
注意!!! 一定要确认python 软连接是否正确 不然会在下面的验证中出错
6.安装gtkwave
sudo apt-get install gtkwave
7.安装GNU工具链
可以从百度网盘下载(链接:https://pan.baidu.com/s/10uLZYf_cgtH94kZI_N6JhQ 提取码:uk0w)或者自行下载其他版本的,下载后解压到tools目录下。
最后,需要确认tests/example/common.mk文件里的这几行内容要与你安装的工具链对应得上。
我建议是百度网盘下载 嘿嘿
然后用git把工程拉近linux 下 git clone https://gitee.com/liangkangnan/tinyriscv.git
进入之后,进入文件夹的sim下列
在终端执行 python .\sim_new_nowave.py ..\tests\isa\generated\rv32ui-p-add.bin inst.data
会出现大大的pass
指令的全部测试 输入 python ./test_all_isa.py
下面进入 C语言的运行
进入 tests\example 下的文件夹 的simple
其实后面的gpio uart_rx uart_tx 都是写好的c程序 这次我们在linux上只实现 simple 的测试
因为已经有Makefile文件了 我们现在进入 在终端输入make 发现可能会报错
是因为
第一行是我们把下载的工具链放在哪里了
后面是修改工具链的来源
1
2 RISCV_PATH := $(TOOLCHAIN_DIR)/tools/riscv64-unknown-elf-gcc-8.3.0-2020.04.0 -x86_64-linux-ubuntu14/
3
4 RISCV_GCC := $(abspath $(RISCV_PATH)/bin/riscv64-unknown-elf-gcc)
5 RISCV_AS := $(abspath $(RISCV_PATH)/bin/riscv64-unknown-elf-as)
6 RISCV_GXX := $(abspath $(RISCV_PATH)/bin/riscv64-unknown-elf-g++)
7 RISCV_OBJDUMP := $(abspath $(RISCV_PATH)/bin/riscv64-unknown-elf-objdump)
8 RISCV_GDB := $(abspath $(RISCV_PATH)/bin/riscv64-unknown-elf-gdb)
9 RISCV_AR := $(abspath $(RISCV_PATH)/bin/riscv64-unknown-elf-ar)
10 RISCV_OBJCOPY := $(abspath $(RISCV_PATH)/bin/riscv64-unknown-elf-objcopy)
11 RISCV_READELF := $(abspath $(RISCV_PATH)/bin/riscv64-unknown-elf-readelf)
12
13 .PHONY: all
14 all: $(TARGET)
15
16 ASM_SRCS += $(COMMON_DIR)/start.S
17 ASM_SRCS += $(COMMON_DIR)/trap_entry.S
18 C_SRCS += $(COMMON_DIR)/init.c
19 C_SRCS += $(COMMON_DIR)/trap_handler.c
20 C_SRCS += $(COMMON_DIR)/lib/utils.c
21 C_SRCS += $(COMMON_DIR)/lib/xprintf.c
22 C_SRCS += $(COMMON_DIR)/lib/uart.c
<inyriscv/tests/example(复件)/common.mk" 57L, 1929C 1,0-1 顶端
修改之后再make就完成了
编译得到bin文件再在 sim 目录里 输入
python .\sim_new_nowave.py ..\tests\example\simple\simple.bin inst.data
即可
注意在Linux 下运行把这样的下划线改成/
最后出来的成功图片是pass
注意点 : 运行的时候确保自己的python的软链接无误
生成的.vcd文件 我们可以通过GTKWave来打开
移植到FPGA
移植到FPGA 需要购买一个下载器
CMSIS-DAP 用的是 jtag 的形式
我购买的是 UART下载的方式
【淘宝】https://m.tb.cn/h.5pXZXZh3DoyfPAx?tk=OvF8W6t8xN8 CZ0001 「usb转ttl usb转串口下载线ch340g模块rs232升级板刷机线板PL2303」
点击链接直接打开 或者 淘宝搜索直接打开
我买的是那个8.52元的 土豪金版本
其实下载到无所谓 但是RISC V仅支持JTAG调试 调试还是换JTAG吧
移植的板卡型号是正点原子达芬奇开发板——Xilinx A7系列 xc7a35tfgg484-2—vivado使用的是2019.1
在执行前 将 整个rtl文件夹 拉入 file中
最重要的是板卡不同的管脚约束问题
我们移植到的达芬奇开发板LED必须输出高电平才能点亮LED灯,在源码中over等三个我们将其绑定至LED灯上
而TinyRisc-V的LED灯是低电平 所以我们需要修改源码,将其变为高电平。
在顶层里修改
修改之后使其能够正常点灯
接下来修改串口tx和 rx信号引脚绑定
这里想要说明的是 其实绝大部分都可以绑定空的引脚,但是一定要绑定,不绑定过不了验证。 我们想要实现某些功能,让它表现出来,最好的办法就是输出在LED灯上。
由于达芬奇开发板没有拨码和自锁开关,并且未按下时按键端口输出高电平,按下时输出低电平。因为这里是高电位启动,所以我们需要修改代码,绑定至key0
修改后为
uart_tx_pin 与 uart_rx_pin 绑定至任意管脚 无需修改
AB6 V7
GPIO[0] 接入 F16
GPIO[1] 接入 F15
jtag_TCK AA8
jtag_TMS AB8
jtag_TDI Y7
jtag_TDO Y8
spi_miso F14
spi_mosi F13
spi_ss E13
spi_clk E14
下面展示完整的管脚约束
# 时钟约束50MHz,占空比50%
create_clock -add -name sys_clk_pin -period 20.00 -waveform {0 10} [get_ports {clk}];
# 时钟引脚
set_property -dict { PACKAGE_PIN R4 IOSTANDARD LVCMOS33 } [get_ports {clk}];
# 复位引脚
set_property -dict { PACKAGE_PIN U2 IOSTANDARD LVCMOS33 } [get_ports {rst}];
# 程序执行完毕指示引脚,over 为1时有效,点亮led0
set_property -dict { PACKAGE_PIN R2 IOSTANDARD LVCMOS33 } [get_ports {over}];
# 程序执行成功指示引脚,succ 为1时有效,点亮led1
set_property -dict { PACKAGE_PIN R3 IOSTANDARD LVCMOS33 } [get_ports {succ}];
# CPU停住指示引脚,halted_ind 为1时有效,点亮led2
set_property -dict { PACKAGE_PIN V2 IOSTANDARD LVCMOS33 } [get_ports {halted_ind}];
# 串口下载使能引脚,由于没有拨码开关和自锁开关,所以绑定到key0上,key0按住不放时才使能串口下载
set_property -dict { PACKAGE_PIN T1 IOSTANDARD LVCMOS33 } [get_ports {uart_debug_pin}];
# 串口发送引脚
set_property -dict { PACKAGE_PIN AB6 IOSTANDARD LVCMOS33 } [get_ports {uart_tx_pin}];
# 串口接收引脚
set_property -dict { PACKAGE_PIN V7 IOSTANDARD LVCMOS33 } [get_ports {uart_rx_pin}];
# GPIO0引脚
set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports {gpio[0]}];
# GPIO1引脚
set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports {gpio[1]}];
# JTAG TCK引脚 PortA 0
set_property -dict { PACKAGE_PIN AA8 IOSTANDARD LVCMOS33 } [get_ports {jtag_TCK}];
create_clock -name jtag_clk_pin -period 300 [get_ports {jtag_TCK}];
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_TCK]
# JTAG TMS引脚 PortA 3
set_property -dict { PACKAGE_PIN AB8 IOSTANDARD LVCMOS33 } [get_ports jtag_TMS];
# JTAG TDI引脚 PortA 1
set_property -dict { PACKAGE_PIN Y7 IOSTANDARD LVCMOS33 } [get_ports {jtag_TDI}];
# JTAG TDO引脚 PortA 2
set_property -dict { PACKAGE_PIN Y8 IOSTANDARD LVCMOS33 } [get_ports jtag_TDO];
# SPI MISO引脚
set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports {spi_miso}];
# SPI MOSI引脚
set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports {spi_mosi}];
# SPI SS引脚
set_property -dict { PACKAGE_PIN E13 IOSTANDARD LVCMOS33 } [get_ports {spi_ss}];
# SPI CLK引脚
set_property -dict { PACKAGE_PIN E14 IOSTANDARD LVCMOS33 } [get_ports {spi_clk}];
#SPI 相关设置
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design]
因为我仅仅在windows上运行
所以我 只安装了python 环境 用脚本驱动 在linux下编译
首先
回到unbuntu 打开 tests/example 做一个串口发送的实验
在uart_tx下 make 其实最好修改一下main.c 让它一直跑 不然看不太到实验效果
make得到bin 文件
我会把bin文件复制到 windows下 嘿嘿
接下来
打开windows自带的powershell
进入 存放这个工程包tools的地方 我们要启动 python脚本了
因为tools下有 python的脚本
然后运行
python .\tinyriscv_fw_downloader.py COM3 D:\Competition\Data\TinyRisc-v\bin\uart_tx.bin
python tinyriscv_fw_downloader.py 串口号 bin文件
COM3是连接的串口号 后面是bin存放地方
打开串口助手 会看到hello world 一直在发送
实验完成
成功标志如下所示
RXD 接AB6
TXD 接V7