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