5394|3

1377

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

【Perf-V评测】移植蜂鸟E203开源SOC到FPGA板 [复制链接]

本帖最后由 cruelfox 于 2021-6-17 23:10 编辑

  Perf-V开发板资料里面有E203 SOC移植好的工程,但是因为用的Vivado版本比我装的高,软件不能全部导进来,主要是因为其中两个Xilinx IP核的问题。

  我用Vivado中的IP Catalog重新定制了这两个模块的IP,但不知什么原因,最终生成的系统没有能够正常工作。原始工程(软件版本更高)中的 .bit 文件直接下载到 FPGA 中是可以工作的(JTAG连接可以发现RISC-V CPU),说明代码结构是没有问题的。于是我用它作参考,自己移植一下这个SOC.

 

  上一篇帖子中我分享了E203 SOC RTL代码的仿真,将这套代码移植到FPGA的操作需要另外编写一个顶层模块,不用仿真测试的顶层模块(文件 tb_top.v)。在Perf-V自带FPGA工程中,顶层模块代码是 system.v, 相当于在 e203_soc_top 这个模块外面再套一层“壳",将FPGA管脚信号连上去。

  看看 e203_soc_top 模块的输入输出端口:

  时钟信号及使能:有高频(HF)和低频(LF)两个时钟输入,分别是16MHz和32.768kHz. 使能信号是给出去的,可以不连。

  input  hfextclk,
  output hfxoscen,

  input  lfextclk,
  output lfxoscen,

  JTAG口的信号:除了TDO都是输入,TDO还有一个输出使能信号。

  input   io_pads_jtag_TCK_i_ival,
  input   io_pads_jtag_TMS_i_ival,
  input   io_pads_jtag_TDI_i_ival,
  output  io_pads_jtag_TDO_o_oval,
  output  io_pads_jtag_TDO_o_oe,

  32个GPIO口的信号,每个口都有6个信号。

  input   io_pads_gpio_0_i_ival,
  output  io_pads_gpio_0_o_oval,
  output  io_pads_gpio_0_o_oe,
  output  io_pads_gpio_0_o_ie,
  output  io_pads_gpio_0_o_pue,
  output  io_pads_gpio_0_o_ds,

  ......
  QSPI flash连接的信号,其中 DQ[n] 是双向端口,因此每个口也有6个信号。

  output  io_pads_qspi_sck_o_oval,
  output  io_pads_qspi_cs_0_o_oval,
  input   io_pads_qspi_dq_0_i_ival,
  output  io_pads_qspi_dq_0_o_oval,
  output  io_pads_qspi_dq_0_o_oe,
  output  io_pads_qspi_dq_0_o_ie,
  output  io_pads_qspi_dq_0_o_pue,
  output  io_pads_qspi_dq_0_o_ds,
  ......

  额外的控制信号:

  // Erst is input need to be pull-up by default
  input   io_pads_aon_erst_n_i_ival,

  // dbgmode are inputs need to be pull-up by default
  input  io_pads_dbgmode0_n_i_ival,
  input  io_pads_dbgmode1_n_i_ival,
  input  io_pads_dbgmode2_n_i_ival,

  // BootRom is input need to be pull-up by default
  input  io_pads_bootrom_n_i_ival,

  // dwakeup is input need to be pull-up by default
  input  io_pads_aon_pmu_dwakeup_n_i_ival,

      // PMU output is just output without enable
  output io_pads_aon_pmu_padrst_o_oval,
  output io_pads_aon_pmu_vddpaden_o_oval 

 

  在Perf-V提供demo的 system.v 文件中,定义了一些 FPGA 的输入输出端口。比如 Perf-V 板子上的 LED、RGB LED、按键、拨动开关、插座引出的I/O口、JTAG口等。特殊管脚比如时钟、JTAG,需要和板子适配;至于 E203 的 32 个GPIO口怎么对应到这些LED、开关、插座上去,可以随自己便。

  E203的一个GPIO口有6个信号,只须对应到FPGA的一个引脚。在demo的 system.v 中是这样写的:

  wire iobuf_gpio_7_o;
  IOBUF
  #(
    .DRIVE(12),
    .IBUF_LOW_PWR("TRUE"),
    .IOSTANDARD("DEFAULT"),
    .SLEW("SLOW")
  )
  IOBUF_gpio_7
  (
    .O(iobuf_gpio_7_o),
    .IO(gpio_7),
    .I(dut_io_pads_gpio_7_o_oval),
    .T(~dut_io_pads_gpio_7_o_oe)
  );
  assign dut_io_pads_gpio_7_i_ival = iobuf_gpio_7_o & dut_io_pads_gpio_7_o_ie;

  这里 IOBUF 的写法是 Xilinx 软件支持的,含义可以猜出来。输出使能信号 dut_io_pads_gpio_7_o_oe 决定了实际 FPGA 引脚是否驱动(输出),输入使能信号 dut_io_pads_gpio_7_o_ie 是决定引脚上的电平状态是否反映到内部信号,还有 dut_io_pads_gpio_7_o_pue (上拉允许) 和 dut_io_pads_gpio_7_o_ds (用途不明确?) 两个信号就没有使用。好象 FPGA 不支持动态改变引脚的上拉功能,所以用不上。

  GPIO在板子上的分配,demo里面写得略复杂了一点。我就先给简化了:GPIO0~8 直接连到三个 RGB LED,其余连到 Arduino 接口,再剩下的连到 PMOD 口上去。

	assign led0_r = gpio_0;
	assign led0_g = gpio_1;
	assign led0_b = gpio_2;
	assign led1_r = gpio_3;
	assign led1_g = gpio_4;
	assign led1_b = gpio_5;
	assign led2_r = gpio_6;
	assign led2_g = gpio_7;
	assign led2_b = gpio_8;

	assign arduino_a[0] = gpio_9;
	assign arduino_a[1] = gpio_10;
	assign arduino_a[2] = gpio_11;
	assign arduino_a[3] = gpio_12;
	assign arduino_a[4] = gpio_13;
	assign arduino_a[5] = gpio_14;

	assign arduino_d[0] = gpio_15;
	assign arduino_d[1] = gpio_16;
	assign arduino_d[2] = gpio_17;
	assign arduino_d[3] = gpio_18;
	assign arduino_d[4] = gpio_19;
	assign arduino_d[5] = gpio_20;
	assign arduino_d[6] = gpio_21;
	assign arduino_d[7] = gpio_22;
	assign arduino_d[8] = gpio_23;
	assign arduino_d[9] = gpio_24;
	assign arduino_d[10] = gpio_25;
	assign arduino_d[11] = gpio_26;
	assign arduino_d[12] = gpio_27;
	assign arduino_d[13] = gpio_28;

	assign pmod_io[0] = gpio_29;
	assign pmod_io[1] = gpio_30;
	assign pmod_io[2] = gpio_31;

 

  E203 SOC 的主时钟是 16MHz, 但开发板的晶振是 50MHz. 因此这里需要一个 PLL 把时钟转换一下。这就要用到 FPGA 提供的 IP 了。参考 demo 的实现,用一个 MMCM IP模块,得到 16MHz 和 8.388MHz 两个时钟,再将 8.388MHz 1/256分频到32768kHz左右作为 LF 时钟。暂时也不需要很准。其实 16MHz 也不是必须的,比如直接将 50MHz 分频到 25MHz 或 12.5MHz 给 RISC-V 用也问题不大,除了UART时钟受影响要重新设以外。

  E203 SOC 的复位信号(输入)是 io_pads_aon_erst_n_i_ival, 在 demo 里面用了一个复位模块IP来提供,但是我之前遇到的失败就从这里引起。于是我不用它,简单点就用 PLL 的锁定信号和外部复位按键组合代替了:

	assign reset_periph = ~ck_rst | ~mmcm_locked;
  assign dut_io_pads_aon_erst_n_i_ival = ~reset_periph;

  JTAG的4个信号照着 demo 里面那样处理,这是必不可缺少的。QSPI 的信号是连到板子上 flash 的,用来存放RISC-V程序。在调试阶段可以先不管 QSPI.

  连接好 FPGA 接口以后就可以开始软件综合了,发现错误再回去改。

 

  还有一个工作是将 FPGA 的接口信号映射到 FPGA 管脚。demo工程里面已经有约束文件了,可以提取出来修改了用,不然全照着电路图一个一个设管脚就很繁琐了。

  完成综合实现之后,Vivado显示的 FPGA 资源使用情况:

  将生成的 .bit 文件下载到 FPGA 中之后,需要检查SOC的工作情况。这一步需要借助调试器,从SOC的JTAG口访问内部资源。这个JTAG不是FPGA的JTAG, 而是FPGA用户逻辑实现的和RISC-V相连的JTAG. 在开发板上两个JTAG口的针脚定义也一样,PerfXLab的下载线也应该是支持两种JTAG用法的。但是我不想拔来插去的,就用另外的工具来处理RISC-V这边的JTAG了。

  我用了一片 FT232R 当作调试硬件,用 openocd 连接开发板上的 E203 SOC:

有这样的信息提示就表示识别到 RISC-V CPU 了。

 

  因为现在系统里面没有程序,CPU当处于异常状态。

Open On-Chip Debugger
> halt
> reg pc
pc (/32): 0x00000000

> step
halted at 0x0 due to step
> mdw 0 4
0x00000000: 00000000 00000000 00000000 00000000

>
  要执行程序,一种办法是用 openocd 直接将代码写到内存里面去,然后修改 PC 寄存器,执行。

> load_image f:/rv32.hex
1602 bytes written at address 0x80000000
72 bytes written at address 0x80001000
16 bytes written at address 0x80002fb8
downloaded 1690 bytes in 1.156250s (1.427 KiB/s)

> resume 0x80000000
> halt
halted at 0x80000090 due to debug interrupt
>

  GDB也可以拿来调试程序。

GNU gdb (GDB) 8.3.0.20190516-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=i686-w64-mingw32 --target=riscv-nuclei-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) set arch riscv:rv32
The target architecture is assumed to be riscv:rv32
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
0x80000090 in ?? ()
(gdb) x /3i $pc
=> 0x80000090:  sw      gp,-140(t5)
   0x80000094:  j       0x80000086
   0x80000096:  auipc   a0,0x2
(gdb) si
halted at 0x80000094 due to step
0x80000094 in ?? ()
(gdb) si
halted at 0x80000086 due to step
0x80000086 in ?? ()
(gdb) si
halted at 0x80000088 due to step
0x80000088 in ?? ()
(gdb) si
halted at 0x8000008c due to step
0x8000008c in ?? ()
(gdb) si
halted at 0x80000090 due to step
0x80000090 in ?? ()

  上面载入内存的代码是E203代码树中测试指令集的一个程序,看起来,测试内容完成之后就进入一个循环了。单步跟踪的结果是 0x80000086 到 0x80000094 之间循环。

  看一下程序的 dump 内容对比:

80000086 <write_tohost>:
80000086:	4521                	li	a0,8
80000088:	30052073          	csrs	mstatus,a0
8000008c:	00001f17          	auipc	t5,0x1
80000090:	f63f2a23          	sw	gp,-140(t5) # 80001000 <tohost>
80000094:	bfcd                	j	80000086 <write_tohost>

  这样的程序没有进行 I/O 操作,不能从硬件上观察到变化。下面需要用程序测试下 GPIO.

此帖出自FPGA/CPLD论坛

最新回复

RPM
请问相关工程博主还有保存吗?澎峰那资料下载不了了   详情 回复 发表于 2023-5-8 20:28
点赞 关注
 

回复
举报

1377

帖子

2

TA的资源

五彩晶圆(初级)

沙发
 

  E203 SOC 里的 GPIO 设备寄存器表:

  简单的 LED 操作只需要使能 GPIO 输出 (output_en对应位写1),然后写输出数据寄存器就可以了。GPIO的设备基地址是 0x10012000,因此直接写个程序来点亮板上的 RGB LED:

#include<stdint.h>

typedef struct{
uint32_t pin;
uint32_t in_en;
uint32_t out_en;
uint32_t odata;
}GPIO_Type;

volatile GPIO_Type * GPIO = (volatile GPIO_Type *)0x10012000;

void micro_delay(void)
{
	int i;
	for(i=0;i<100;i++)
	{
		asm volatile ("nop\n");
		asm volatile ("nop\n");
	}
}

void test(void)
{
	int r,g,b;

	GPIO->out_en = 7;
	for(;;)
	{
		for(r=0;r<=8;r++)
		{
			for(g=0;g<=8-r;g++)
			{
				int t;
				b=8-r-g;
				for(t=0;t<2000;t++)
				{
					int i;
					GPIO->odata = 0x1FE;	// show R
					for(i=0;i<r;i++)
						micro_delay();
					GPIO->odata = 0x1FD;	// show G
					for(i=0;i<g;i++)
						micro_delay();
					GPIO->odata = 0x1FB;	// show B
					for(i=0;i<b;i++)
						micro_delay();
				}
			}
		}
	}
}

  变色的效果就是 R/G/B 交替亮的时间不等,并逐渐改变时长造成。至于延时,用最简单的空指令加循环。

 

  类比ARM cortex-M0平台的编译方法,用RISC-V的toolchain来干活:

  编译C文件:

riscv-nuclei-elf-gcc -c -Os led.c -march=rv32imc -mabi=ilp32

指定了指令集分支为 RV32IMC, 这里用的指令简单,估计不指定也能工作。ABI指定如果省略了,GCC会报错。

  链接成ELF:

riscv-nuclei-elf-ld led.o -Ttext 0x80000000

指定了代码段的位置,0x80000000 是 E203 SOC 的 ITCM RAM.

  反汇编看程序代码:

riscv-nuclei-elf-objdump -d a.out

Disassembly of section .text:

80000000 <micro_delay>:
80000000:       06400793                li      a5,100
80000004:       0001                    nop
80000006:       0001                    nop
80000008:       17fd                    addi    a5,a5,-1
8000000a:       ffed                    bnez    a5,80000004 <micro_delay+0x4>
8000000c:       8082                    ret

8000000e <test>:
8000000e:       7179                    addi    sp,sp,-48
80000010:       d422                    sw      s0,40(sp)
80000012:       80001437                lui     s0,0x80001
80000016:       0a442783                lw      a5,164(s0) # 800010a4 <__global_pointer$+0xfffff800>
8000001a:       c65e                    sw      s7,12(sp)
8000001c:       c462                    sw      s8,8(sp)
8000001e:       c266                    sw      s9,4(sp)
80000020:       c06a                    sw      s10,0(sp)
80000022:       d606                    sw      ra,44(sp)
80000024:       d226                    sw      s1,36(sp)
80000026:       d04a                    sw      s2,32(sp)
80000028:       ce4e                    sw      s3,28(sp)
8000002a:       cc52                    sw      s4,24(sp)
8000002c:       ca56                    sw      s5,20(sp)
8000002e:       c85a                    sw      s6,16(sp)
80000030:       471d                    li      a4,7
80000032:       c798                    sw      a4,8(a5)
80000034:       1fe00b93                li      s7,510
80000038:       1fd00c13                li      s8,509
8000003c:       1fb00c93                li      s9,507
80000040:       4d25                    li      s10,9
80000042:       4921                    li      s2,8
80000044:       4981                    li      s3,0
80000046:       8a4a                    mv      s4,s2
80000048:       4481                    li      s1,0
8000004a:       a82d                    j       80000084 <test+0x76>
8000004c:       7d000a93                li      s5,2000
80000050:       0a442783                lw      a5,164(s0)
80000054:       4b01                    li      s6,0
80000056:       0177a623                sw      s7,12(a5)
8000005a:       033b1c63                bne     s6,s3,80000092 <test+0x84>
8000005e:       0a442783                lw      a5,164(s0)
80000062:       4b01                    li      s6,0
80000064:       0187a623                sw      s8,12(a5)
80000068:       03649863                bne     s1,s6,80000098 <test+0x8a>
8000006c:       0a442783                lw      a5,164(s0)
80000070:       4b01                    li      s6,0
80000072:       0197a623                sw      s9,12(a5)
80000076:       034b4463                blt     s6,s4,8000009e <test+0x90>
8000007a:       1afd                    addi    s5,s5,-1
8000007c:       fc0a9ae3                bnez    s5,80000050 <test+0x42>
80000080:       0485                    addi    s1,s1,1
80000082:       1a7d                    addi    s4,s4,-1
80000084:       fc9954e3                bge     s2,s1,8000004c <test+0x3e>
80000088:       0985                    addi    s3,s3,1
8000008a:       197d                    addi    s2,s2,-1
8000008c:       fba99de3                bne     s3,s10,80000046 <test+0x38>
80000090:       bf4d                    j       80000042 <test+0x34>
80000092:       37bd                    jal     80000000 <micro_delay>
80000094:       0b05                    addi    s6,s6,1
80000096:       b7d1                    j       8000005a <test+0x4c>
80000098:       37a5                    jal     80000000 <micro_delay>
8000009a:       0b05                    addi    s6,s6,1
8000009c:       b7f1                    j       80000068 <test+0x5a>
8000009e:       378d                    jal     80000000 <micro_delay>
800000a0:       0b05                    addi    s6,s6,1
800000a2:       bfd1                    j       80000076 <test+0x68>

因为使用了压缩指令,所以指令长度是32-bit, 16-bit混合的。

  生成 bin 文件:

riscv-nuclei-elf-objcopy -Obinary a.out led.bin

 

  然后,在 openocd 中装载这个 .bin 程序文件:

> halt
halted at 0x80000008 due to debug interrupt
> load_image f:/led.bin 0x80000000
4264 bytes written at address 0x80000000
downloaded 4264 bytes in 2.734375s (1.523 KiB/s)

  因为没有初始化代码,需要手动初始化一下堆栈,然后设置PC运行的地址:

> reg sp 0x90001000

> resume 0x8000000e

  这样就能从 test() 函数的入口开始运行了,可看到 RGB LED 的变化。

此帖出自FPGA/CPLD论坛
 
 

回复

6802

帖子

0

TA的资源

五彩晶圆(高级)

板凳
 

用Vivado显示的 FPGA 资源使用情况,这个功能还是不错的

直接用JTAG连接可以发现RISC-V CPU

谢谢分享

此帖出自FPGA/CPLD论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 

请问相关工程博主还有保存吗?澎峰那资料下载不了了

此帖出自FPGA/CPLD论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表