旧板子新玩法——DE2上运行Freedom E310

众所周知,我有一块旧板子DE2-35,很久很久的那种,大概有十多年历史了,不过好在保养得比较好,现在还完好如初,最近心血来潮,打算在上面运行Freedom E310

Freedom E310是一个开源SoC,其处理器核心是RISC-V架构的开源处理器E3 Coreplex,由SiFive公司设计发布的。

E310的结构图如下所示,从图中可知,除了处理器E3 Coreplex,还有比较丰富的外设,包括:GPIO控制器、AONQSPI控制器等。其中GPIO接口是可以复用的,可以有复用为两个UART、两个PWM、两个QSPI

旧板子新玩法——DE2上运行Freedom E310_第1张图片

Freedom E310已经在XilinxDigilent Arty开发板上运行成功,并且官网提供了完整的工程文件,没有Digilent Arty的童鞋也不要灰心,下面就是Freedom E31010年前的DE2上的移植测试过程,旧板子新玩法,没有Digilent Arty,照样可以玩转Freedom E310。开发主机是Ubuntu14.04

一、Quartus工程建立

1clone代码

Githubclone下列项目的代码:Rocket-chipFreedomFreedom-e-sdk。因为Freedom-e-sdk没有clone下来,所以这里的测试程序是使用Rocket-chipriscv64-unknown-elf-gcc编译的,网速快的童鞋可以直接使用Freedom-e-sdk中的gcc编译器。

2、编译Rocket-chip

具体步骤就不说了,在Readme中都有详细的描述。这次编译的目的是安装GCC编译器。

3、编译Freedom

进入Freedom路径,使用如下语句:

make -f Makefile.e300artydevkit verilog

会在build目录下得到一个sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.v

4、建立Quartus工程

新建一个Quartus工程,将上面得到的verilog文件,以及面几个文件添加到该工程中:

freedom\fpga\e300artydevkit\src\system.v
freedom\sifive-blocks\vsrc\SRLatch.v
freedom\rocket-chip\vsrc\AsyncResetReg.v
freedom\rocket-chip\vsrc\DebugTransportModuleJtag.v


5、使用Megawizard Plug-in Manager得到PLL

命名为mmcm,输入频率是27MHz,输出有两个,c010.125MHzc127MHz,其中c1是作为处理器的主时钟,另外,还有一个locked信号输出,表示PLL是否稳定。具体步骤如下面图所示:

旧板子新玩法——DE2上运行Freedom E310_第2张图片

旧板子新玩法——DE2上运行Freedom E310_第3张图片

旧板子新玩法——DE2上运行Freedom E310_第4张图片

旧板子新玩法——DE2上运行Freedom E310_第5张图片

然后注释掉system.v中的如下代码:

mmcm ip_mmcm
(
    .clk_in1(CLK100MHZ),
    .clk_out1(clk_out1), // 8.388 MHz = 32.768 kHz * 256
    .clk_out2(hfclk), // 65 MHz
    .resetn(ck_rst),
    .locked(mmcm_locked)
  );

改为如下:

mmcm ip_mmcm
	(
	  .areset(ck_rst),
	  .inclk0(CLK100MHZ),     // 27 MHz
	  .c0(clk_out1),          // 10.125Mhz
	  .c1(hfclk),             // 27MHz
	  .locked(mmcm_locked)
	);

6、继续修改system.v

修改clkdivider的例化,改为如下:

 clkdivider slowclkgen
  (
.clk(clk_out1),   
    .reset(ck_rst),            
    .clk_out(slowclk)          
  );

7、继续修改system.v

注释掉reset_sys的例化部分,使用如下代码代替:

reg reset_periph_t;
    always @(posedge clk_out1)
    begin
      if( ck_rst  == 1'b1 || mmcm_locked == 1'b0 || SRST_n == 1'b0)  begin
          reset_periph_t <= 1'b1;
      end else begin
          reset_periph_t <= 1'b0;
      end 
    end
assign reset_periph = reset_periph_t;

8、继续修改system.v

使用下面的方法替换所有的IOBUF例化,因为IOBUFXilinx的原语。

IOBUF
  #(
    .DRIVE(12),
    .IBUF_LOW_PWR("TRUE"),
    .IOSTANDARD("DEFAULT"),
    .SLEW("SLOW")
  )
  IOBUF_gpio_1
  (
    .O(iobuf_gpio_1_o),
    .IO(gpio_1),
    .I(dut_io_pads_gpio_1_o_oval),
    .T(~dut_io_pads_gpio_1_o_oe)
  );

可以使用如下语句代替:

 assign gpio_1 = dut_io_pads_gpio_1_o_oe ? dut_io_pads_gpio_1_o_oval : 1'bz;
  assign iobuf_gpio_1_o = gpio_1;

9、端口分配

这里只是打算做一个简单的GPIO实验,所以没有没有连接全部的端口,主要如下:

CLK100MHZ——连接板载的27MHz时钟

ck_rst——连接波动开关SW1,作为复位按钮

jd_6——连接拨动开关SW0,要确保使其处于高电位

ck_io[8]——实际就是对应E310GPIO0,连接绿色LED0

ck_io[9]——实际就是对应E310GPIO1,连接绿色LED1

ck_io[10]——实际就是对应E310GPIO2,连接绿色LED2

如下:

set_location_assignment PIN_D13 -to CLK100MHZ
set_location_assignment PIN_AE22 -to ck_io[8]
set_location_assignment PIN_AF22 -to ck_io[9]
set_location_assignment PIN_W19 -to ck_io[10]
set_location_assignment PIN_N26 -to ck_rst
set_location_assignment PIN_N25 -to jd_6

system.v设置为顶层文件,就可以编译该工程了。但此时下载到DE2上还是观察不到效果的,因为我们还没有编写测试程序。

二、测试程序的编写

使用汇编编写,打开rocket-chip\bootrom文件夹下的bootrom.S文件,改为如下内容:

.text
.global _start
_start:
  // This boot ROM doesn't know about any boot devices, so it just spins,
  // waiting for the debugger to load a program and change the PC.
  j 1f // reset vector
  nop
  nop
  .word 0 // reserved
  .word 0 // reserved
  .word 0 // pointer to config string
  .word 0 // default trap vector
  .word 0
  .word 0
  .word 0
1:
  li x1, 0x7
  li x2,0x10012008   // make GPIO0  GPIO1  GPIO2 out port
  sw x1,0(x2)


  li x3, 0
  li x5,1 

2:

// light Green LED2,  then wait few seconds
  li x1, 0x04
  li x2,0x1001200C
  sw x1,0(x2)


  li x4,0x1dfd240
3:
  sub x4,x4,x5
  bne x4,x3,3b

// light Green LED1,  then wait few seconds
  li x1, 0x02
  li x2,0x1001200C
  sw x1,0(x2)


  li x4,0x1dfd240
4:
  sub x4,x4,x5
  bne x4,x3,4b

// light Green LED0,  then wait few seconds
  li x1, 0x01
  li x2,0x1001200C
  sw x1,0(x2)

  li x4,0x1dfd240
5:
  sub x4,x4,x5
  bne x4,x3,5b

  j 2b
  nop

整个程序很简单,启动后,首先初始化GPIO,设置GPIO0GPIO1GPIO2为输出口,然后依次通过这三个端口输出高电平,每输出一个高电平,就等待一段时间,然后再在下一个端口输出高电平,其中用到了E310的地址空间映射,GPIO对应的地址映射如下:

旧板子新玩法——DE2上运行Freedom E310_第6张图片


内部的配置寄存器地址偏移如下: 旧板子新玩法——DE2上运行Freedom E310_第7张图片

所以0x10012008就是配置输出使能的地址,0x1001200C就是设置输出值的地址,这样一说就容易理解上面的程序了。

还是在rocket-chip\bootrom目录下,使用已有的链接脚本,如下:

SECTIONS
{
    . = 0x1000;
    .text : { *(.text) }
}

因为E310复位的地址是0x1000,所以上面的测试程序就从0x1000开始执行。然后使用下面的两条语句编译:

riscv64-unknown-elf-gcc -Tlinker.ld bootrom.S -nostdlib -static -o bootrom.elf -m32
riscv64-unknown-elf-objcopy -O binary --change-addresses=-0x1000 --only-section .text bootrom.elf bootrom.img

将上面的bootrom.img,复制到freedom项目路径下的bootrom,重命名为e300artydevkit.img

freedom路径下,使用如下语句得到新的verilog代码:

make -f Makefile.e300artydevkit clean
make -f Makefile.e300artydevkit verilog

新的文件依然位于将freedom/builds/e300artydevkit/路径下,还是sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.v,将该文件复制到Quartus工程中,覆盖之前的文件,然后重新编译Quartus工程,将得到的sof文件下载DE2上,此处就可以观察到实验效果了,三个绿色LED灯依次点亮。




你可能感兴趣的:(RISC-V)