Pulpino SoC中挂载AXI从机接口的自定义IP说明

Pulpino SoC中挂载AXI从机接口的自定义IP说明

本篇文章主要从工程的角度描述了如何将具有AXI从机接口的自定义IP挂载到Pulpino SoC上,其中不涉及到SoC中的任何原理知识。

PULPion SoC介绍

PULPion SoC整体架构如下图所示, PULPino有如下一些特点:
(1)采用的是指令RAM、数据RAM分开的哈佛结构;
(2)增加了一个Boot ROM,其中可以存储启动代码,利用该启动代码可以加载连接至SPI接口的Flash中的程序。
(3)采用的AXI4、APB两级总线结构。
(4)具有外设接口,包括GPIO、UART、I2C、SPI等。
(5)含有一个SoC Controll模块,其作用是整个SoC平台的控制信息,包括:是否使能时钟门、设置启动地址、架构信息等。
(6)提供了一个Advanced Debug Unit,提供了标准调试JTAG接口,使得调试器可以访问指令RAM、数据RAM、处理器内部寄存器,以及外设对应的控制寄存器等。
(7)提供了一个SPI Slave接口,直接连接在AXI互连总线上,可以通过该接口在不影响处理器的情况下,访问指令RAM、数据RAM、处理器内部寄存器,以及外设对应的控制寄存器等。
Pulpino SoC 整体框图
PULPino目前支持4种不同配置的、采用RISC-V指令集的处理器核,如下:
(1)RI5CY:这是最早开源的处理器核,支持RV32-ICM,并且支持算术指令扩展(ALU Extension)、硬件循环(Hardware Loop)、地址自增的访存指令(post-incrementing Load & Strore Instruciton)、乘累加指令(Multiply-Accumulate)、向量操作(Vectorial)等扩展。
(2)RI5CY+FPU:包括RI5CY,以及一个符合IEEE-754标准的单精度FPU。
(3)Zero-riscy:支持RV32-ICM,在占用资源上做了优化。
(4)Micro-riscy: 这是4种配置中占用资源最少的,支持RV32-EC,具有16个寄存器,且不支持硬件乘法。

自定义AXI IP挂载

IP挂载框图

自定义从机接口的IP挂载在AXI4互联单元上,如下图所示。
在这里插入图片描述

代码修改

分析PULPion SoC的顶层代码,其中pulpino_top.sv为SoC的顶层文件,主要包含以下部分:AXI_Bus的主从接口例化,DEBUG_BUS的例化,时钟复位生成模块,RISCV内核,外设peripherals例化和AXI_node例化。修改的主要部分为AXI_Bus的从机接口例化数量,外设peripherals中自定义IP的挂载和AXI_node例化中的地址分配。
AXI_Bus的修改,自定义IP作为一个从机接口,那么将接口数量从3个变为4个,如下所示,AXI_Bus内部不需要进行修改。

  AXI_BUS
  #(
    .AXI_ADDR_WIDTH ( `AXI_ADDR_WIDTH     ),
    .AXI_DATA_WIDTH ( `AXI_DATA_WIDTH     ),
    .AXI_ID_WIDTH   ( `AXI_ID_SLAVE_WIDTH ),
    .AXI_USER_WIDTH ( `AXI_USER_WIDTH     )
  )
  slaves[3:0]();

外设peripherals中自定义IP的挂载,peripherals外设的参数端口和输入输出端口更改如下:

module peripherals
  #(
    parameter AXI_ADDR_WIDTH       = 32,
    parameter AXI_DATA_WIDTH       = 64,
    parameter AXI_USER_WIDTH       = 6,
    parameter AXI_SLAVE_ID_WIDTH   = 6,
    parameter AXI_MASTER_ID_WIDTH  = 6,
    parameter ROM_START_ADDR       = 32'h8000,
    //modified parameter start
    parameter ControlReg0_Addr     = 32'h80000100,
    parameter ControlReg1_Addr     = 32'h80000110,
    parameter ControlReg2_Addr     = 32'h80000120,
    parameter DataReg_Addr         = 32'h80000130,
    parameter StateReg_Addr        = 32'h80000140,
    parameter SM2_Sign_Addr        = 32'h80000150,
    parameter SM2_Verify_Addr      = 32'h80000160,
    parameter PointMulX_Addr       = 32'h80000170,
    parameter PointMulY_Addr       = 32'h80000180,
    parameter PointAddX_Addr       = 32'h80000190,
    parameter PointAddY_Addr       = 32'h800001a0,
    parameter PointDoubleX_Addr    = 32'h800001b0,
    parameter PointDoubleY_Addr    = 32'h800001c0,
    parameter MonMul_Addr          = 32'h800001d0,
    parameter MulAdd_Addr          = 32'h800001e0,
    parameter MulSub_Addr          = 32'h800001f0,
    parameter Mdi_Addr             = 32'h80000200,
    parameter SM3_Data_Addr        = 32'h80000210,
    parameter SM4_Data_Addr        = 32'h80000220
    //modified parameter end
  )
  (
    // Clock and Reset
    input logic clk_i,
    input logic rst_n,
    // Modified region start
    input logic clk_ecc,
    // Modified region end
    AXI_BUS.Master axi_spi_master,

    DEBUG_BUS.Master debug,

    input  logic             spi_clk_i,
    input  logic             testmode_i,
    input  logic             spi_cs_i,
    output logic [1:0]       spi_mode_o,
    output logic             spi_sdo0_o,
    output logic             spi_sdo1_o,
    output logic             spi_sdo2_o,
    output logic             spi_sdo3_o,
    input  logic             spi_sdi0_i,
    input  logic             spi_sdi1_i,
    input  logic             spi_sdi2_i,
    input  logic             spi_sdi3_i,

    AXI_BUS.Slave  slave,
    // Modified region start
    AXI_BUS.Slave  Ecc_slave,
    // Modified region end
    output logic              uart_tx,
    input  logic              uart_rx,
    output logic              uart_rts,
    output logic              uart_dtr,
    input  logic              uart_cts,
    input  logic              uart_dsr,

    output logic              spi_master_clk,
    output logic              spi_master_csn0,
    output logic              spi_master_csn1,
    output logic              spi_master_csn2,
    output logic              spi_master_csn3,
    output logic       [1:0]  spi_master_mode,
    output logic              spi_master_sdo0,
    output logic              spi_master_sdo1,
    output logic              spi_master_sdo2,
    output logic              spi_master_sdo3,
    input  logic              spi_master_sdi0,
    input  logic              spi_master_sdi1,
    input  logic              spi_master_sdi2,
    input  logic              spi_master_sdi3,

    input  logic              scl_pad_i,
    output logic              scl_pad_o,
    output logic              scl_padoen_o,
    input  logic              sda_pad_i,
    output logic              sda_pad_o,
    output logic              sda_padoen_o,

    input  logic       [31:0] gpio_in,
    output logic       [31:0] gpio_out,
    output logic       [31:0] gpio_dir,
    output logic [31:0] [5:0] gpio_padcfg,

    input  logic              core_busy_i,
    output logic [31:0]       irq_o,
    input  logic              fetch_enable_i,
    output logic              fetch_enable_o,
    output logic              clk_gate_core_o,

    output logic              fll1_req_o,
    output logic              fll1_wrn_o,
    output logic [1:0]        fll1_add_o,
    output logic [31:0]       fll1_wdata_o,
    input  logic              fll1_ack_i,
    input  logic [31:0]       fll1_rdata_i,
    input  logic              fll1_lock_i,

    output logic [31:0] [5:0] pad_cfg_o,
    output logic       [31:0] pad_mux_o,
    output logic       [31:0] boot_addr_o
  );

在输入端口增加了一个外部时钟,作为自定义IP中的算法内核时钟,接口增加了一个AXI从机接口Ecc_slave,将自定义IP例化如下所示,这样就将自定义的AXI接口从机IP挂载到外设上。


  //
  ///                                                            ///
  /// Modified Area                                              ///
  /// AXI ECC Interface                                          ///
  ///                                                            ///
  //

  ECC_AXI  
  #(
      .AXI_ADDRESS_WIDTH (AXI_ADDR_WIDTH     ),
      .AXI_DATA_WIDTH    (AXI_DATA_WIDTH     ),    
      .AXI_USER_WIDTH    (AXI_USER_WIDTH     ),    
      .AXI_ID_WIDTH      (AXI_SLAVE_ID_WIDTH ),
      /*------ ECC parameter ------*/
      .ControlReg0_Addr  (ControlReg0_Addr   ),
      .ControlReg1_Addr  (ControlReg1_Addr   ),
      .ControlReg2_Addr  (ControlReg2_Addr   ),
      .DataReg_Addr      (DataReg_Addr       ),
      .StateReg_Addr     (StateReg_Addr      ),
      .SM2_Sign_Addr     (SM2_Sign_Addr      ),
      .SM2_Verify_Addr   (SM2_Verify_Addr    ),
      .PointMulX_Addr    (PointMulX_Addr     ),
      .PointMulY_Addr    (PointMulY_Addr     ),
      .PointAddX_Addr    (PointAddX_Addr     ),
      .PointAddY_Addr    (PointAddY_Addr     ),
      .PointDoubleX_Addr (PointDoubleX_Addr  ),
      .PointDoubleY_Addr (PointDoubleY_Addr  ),
      .MonMul_Addr       (MonMul_Addr        ),
      .MulAdd_Addr       (MulAdd_Addr        ),
      .MulSub_Addr       (MulSub_Addr        ),
      .Mdi_Addr          (Mdi_Addr           ),
      .SM3_Data_Addr     (SM3_Data_Addr      ),
      .SM4_Data_Addr     (SM4_Data_Addr      )
  ) ECC_AXI_Slave
  (
      /* AXI Slave Signal define */
      .slave    ( Ecc_slave    ),
      .clk_core ( clk_ecc  ),
      .clk_i    ( clk_i    ),
      .resetn_i ( rst_n    )
  );

顶层文件中外设peripherals连接修改添加如下:

  //----------------------------------------------------------------------------//
  // Peripherals
  //----------------------------------------------------------------------------//
  peripherals
  #(
    .AXI_ADDR_WIDTH      ( `AXI_ADDR_WIDTH      ),
    .AXI_DATA_WIDTH      ( `AXI_DATA_WIDTH      ),
    .AXI_SLAVE_ID_WIDTH  ( `AXI_ID_SLAVE_WIDTH  ),
    .AXI_MASTER_ID_WIDTH ( `AXI_ID_MASTER_WIDTH ),
    .AXI_USER_WIDTH      ( `AXI_USER_WIDTH      ),
    //modified parameter start
    .ControlReg0_Addr    (`ControlReg0_Addr     ),
    .ControlReg1_Addr    (`ControlReg1_Addr     ),
    .ControlReg2_Addr    (`ControlReg2_Addr     ),
    .DataReg_Addr        (`DataReg_Addr         ),
    .StateReg_Addr       (`StateReg_Addr        ),
    .SM2_Sign_Addr       (`SM2_Sign_Addr        ),
    .SM2_Verify_Addr     (`SM2_Verify_Addr      ),
    .PointMulX_Addr      (`PointMulX_Addr       ),
    .PointMulY_Addr      (`PointMulY_Addr       ),
    .PointAddX_Addr      (`PointAddX_Addr       ),
    .PointAddY_Addr      (`PointAddY_Addr       ),
    .PointDoubleX_Addr   (`PointDoubleX_Addr    ),
    .PointDoubleY_Addr   (`PointDoubleY_Addr    ),
    .MonMul_Addr         (`MonMul_Addr          ),
    .MulAdd_Addr         (`MulAdd_Addr          ),
    .MulSub_Addr         (`MulSub_Addr          ),
    .Mdi_Addr            (`Mdi_Addr             ),
    .SM3_Data_Addr       (`SM3_Data_Addr        ),
    .SM4_Data_Addr       (`SM4_Data_Addr        )
    //modified parameter end
  )
  peripherals_i
  (
    .clk_i           ( clk_int           ),
    .rst_n           ( rstn_int          ),
    // Modified region start
    .clk_ecc         (clk_ecc),
    // Modified region end

    .axi_spi_master  ( masters[2]        ),
    .debug           ( debug             ),

    .spi_clk_i       ( spi_clk_i         ),
    .testmode_i      ( testmode_i        ),
    .spi_cs_i        ( spi_cs_i          ),
    .spi_mode_o      ( spi_mode_o        ),
    .spi_sdo0_o      ( spi_sdo0_o        ),
    .spi_sdo1_o      ( spi_sdo1_o        ),
    .spi_sdo2_o      ( spi_sdo2_o        ),
    .spi_sdo3_o      ( spi_sdo3_o        ),
    .spi_sdi0_i      ( spi_sdi0_i        ),
    .spi_sdi1_i      ( spi_sdi1_i        ),
    .spi_sdi2_i      ( spi_sdi2_i        ),
    .spi_sdi3_i      ( spi_sdi3_i        ),

    .slave           ( slaves[2]         ),
    // Modified region start
    .Ecc_slave       ( slaves[3]         ),
    // Modified region end
    .uart_tx         ( uart_tx           ),
    .uart_rx         ( uart_rx           ),
    .uart_rts        ( uart_rts          ),
    .uart_dtr        ( uart_dtr          ),
    .uart_cts        ( uart_cts          ),
    .uart_dsr        ( uart_dsr          ),

    .spi_master_clk  ( spi_master_clk_o  ),
    .spi_master_csn0 ( spi_master_csn0_o ),
    .spi_master_csn1 ( spi_master_csn1_o ),
    .spi_master_csn2 ( spi_master_csn2_o ),
    .spi_master_csn3 ( spi_master_csn3_o ),
    .spi_master_mode ( spi_master_mode_o ),
    .spi_master_sdo0 ( spi_master_sdo0_o ),
    .spi_master_sdo1 ( spi_master_sdo1_o ),
    .spi_master_sdo2 ( spi_master_sdo2_o ),
    .spi_master_sdo3 ( spi_master_sdo3_o ),
    .spi_master_sdi0 ( spi_master_sdi0_i ),
    .spi_master_sdi1 ( spi_master_sdi1_i ),
    .spi_master_sdi2 ( spi_master_sdi2_i ),
    .spi_master_sdi3 ( spi_master_sdi3_i ),

    .scl_pad_i       ( scl_pad_i         ),
    .scl_pad_o       ( scl_pad_o         ),
    .scl_padoen_o    ( scl_padoen_o      ),
    .sda_pad_i       ( sda_pad_i         ),
    .sda_pad_o       ( sda_pad_o         ),
    .sda_padoen_o    ( sda_padoen_o      ),

    .gpio_in         ( gpio_in           ),
    .gpio_out        ( gpio_out          ),
    .gpio_dir        ( gpio_dir          ),
    .gpio_padcfg     ( gpio_padcfg       ),

    .core_busy_i     ( core_busy_int     ),
    .irq_o           ( irq_to_core_int   ),
    .fetch_enable_i  ( fetch_enable_i    ),
    .fetch_enable_o  ( fetch_enable_int  ),
    .clk_gate_core_o ( clk_gate_core_int ),

    .fll1_req_o      ( cfgreq_fll_int    ),
    .fll1_wrn_o      ( cfgweb_n_fll_int  ),
    .fll1_add_o      ( cfgad_fll_int     ),
    .fll1_wdata_o    ( cfgd_fll_int      ),
    .fll1_ack_i      ( cfgack_fll_int    ),
    .fll1_rdata_i    ( cfgq_fll_int      ),
    .fll1_lock_i     ( lock_fll_int      ),
    .pad_cfg_o       ( pad_cfg_o         ),
    .pad_mux_o       ( pad_mux_o         ),
    .boot_addr_o     ( boot_addr_int     )
  );

AXI_node中新增的自定义AXI从机外设地址分配,修改如下,NB_MASTER对应的是顶层中AXI从机的数量,NB_SLAVE对应的是顶层中AXI主机的数量,因此,添加一个AXI从机,NB_MASTER由3变为4,同时分配地址,分配地址为32’h1A12_0000 —32’h1A12_0120 。

  //----------------------------------------------------------------------------//
  // Axi node
  //----------------------------------------------------------------------------//

  axi_node_intf_wrap
  #(
    .NB_MASTER      ( 4                    ),
    .NB_SLAVE       ( 3                    ),
    .AXI_ADDR_WIDTH ( `AXI_ADDR_WIDTH      ),
    .AXI_DATA_WIDTH ( `AXI_DATA_WIDTH      ),
    .AXI_ID_WIDTH   ( `AXI_ID_MASTER_WIDTH ),
    .AXI_USER_WIDTH ( `AXI_USER_WIDTH      )
  )
  axi_interconnect_i
  (
    .clk       ( clk_int    ),
    .rst_n     ( rstn_int   ),
    .test_en_i ( testmode_i ),

    .master    ( slaves     ),
    .slave     ( masters    ),

    .start_addr_i ( { 32'h1A12_0000, 32'h1A10_0000, 32'h0010_0000, 32'h0000_0000 } ),
    .end_addr_i   ( { 32'h1A12_0120, 32'h1A11_FFFF, 32'h001F_FFFF, 32'h000F_FFFF } )
  );

以上步骤完成了自定义AXI从机接口的挂载。

脚本修改

修改pulpino/vsim/vcompile文件夹下vcompile_ips.csh文件如图红框所示。
在这里插入图片描述

pulpino/vsim/vcompile/ips文件夹下添加vcompile_axi_ecc.csh文件,修改如下,主要作用是将自定义IP中涉及到的.v和.sv文件包含进行编译。
在这里插入图片描述
在这里插入图片描述
修改pulpino/vsim/vcompile/rtl文件夹下的vcompile_pulpino.sh文件如下,添加自定义IP的顶层文件。
在这里插入图片描述

自定义AXI IP调试

C语言编写

进入文件夹pulpino/sw/app/helloworld,本实验是在已经跑通的helloworld工程下对helloworld.c文件中的内容进行修改,通过地址的方式访问自定义IP。

// Copyright 2017 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License.  You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.


#include <stdio.h>
#include <stdlib.h>
typedef unsigned int  u_int32;
typedef unsigned char u_int8;

/*---- Write Address Region ----*/
#define CR0_Addr             0x1A120000
#define CR1_Addr             0x1A120010
#define CR2_Addr             0x1A120020
#define Data_Addr            0x1A120030
/*----- Write Address End  -----*/

/*----- Read Address Region -----*/
#define StateReg_Addr        0x1A120040
#define SM2_Sign_Addr        0x1A120050
#define SM2_Verify_Addr      0x1A120060
#define PointMulX_Addr       0x1A120070
#define PointMulY_Addr       0x1A120080
#define PointAddX_Addr       0x1A120090
#define PointAddY_Addr       0x1A1200A0
#define PointDoubleX_Addr    0x1A1200B0
#define PointDoubleY_Addr    0x1A1200C0
#define MonMul_Addr          0x1A1200D0
#define MulAdd_Addr          0x1A1200E0
#define MulSub_Addr          0x1A1200F0
#define Mdi_Addr             0x1A120100
#define SM3_Data_Addr        0x1A120110
#define SM4_Data_Addr        0x1A120120
/*------ Read Address End -------*/

/*----- SM3 related Command -----*/
#define SM3_Reset_Cmd        0x2980090
#define SM3_Dnt_1_Cmd        0x980090
#define SM3_Dnt_2_Cmd        0x9a0090
#define SM3_Dnt_3_Cmd        0x9c0090
#define SM3_Dnt_4_Cmd        0x9e0090


#define SM3_Length           2048

/*---- Function Definition ----*/
u_int8 Write_Ctr(volatile int *p, u_int8 Address, u_int32 Data);
void Write_Data_Single(volatile int *p, u_int32 Data);
void Write_Data(volatile int *p, u_int32 Data[], int num);
u_int32 Read_Data_Single(volatile int *p, u_int32 ReadAddr);

u_int32 SM3_Plain_Data[64] = {
    0xd9c8b261, 0xa98980e4, 0x2c4032cb, 0x908ce83b,
    0xff5ebeab, 0xeece074d, 0xbb0ae408, 0x2ab20d4a,
    0x027542b0, 0xc1adbd8a, 0xcf81ae59, 0xc23ee432,
    0x7f3b3eea, 0xe977168a, 0x3ad58a96, 0xd913a365,
    0x42f57e43, 0x2ea4ce37, 0x1d1a0b99, 0x9125886c,
    0x2238ffee, 0xf130ec45, 0x0f2a2f95, 0x2205623c,
    0x8fa6e036, 0xb8192251, 0xfdaa3b3b, 0x8826c333,
    0x18aa6cd7, 0x09fef7fb, 0x77a34a99, 0x9f6b001e,
    0x076513a1, 0x249f32c5, 0xe1f80f5f, 0x9cdb2e45,
    0xcda7dcf2, 0x9b5489de, 0x99f61006, 0x90e55bfb,
    0x7349c7ed, 0x39223d48, 0x7704bb5e, 0x4cb7bd88,
    0xd4c68815, 0x00742937, 0xff6723e8, 0x239a427b,
    0xf9114c12, 0xf0f8c4df, 0xfbcb21a9, 0x010ca68a,
    0x09cf580b, 0xdb51ddba, 0xb77f1062, 0x99f11955,
    0x5689f6f2, 0x8ebef87f, 0x3a693888, 0x575045aa,
    0x5d564a58, 0xacba779a, 0x1aa026dd, 0x352f7ad8 
};

u_int32 SM3_True_Result[8] = {
    0x3c793e03,0x8b639d60,0x9fad8fa5,0xdb89dcc8,
    0x28830616,0x6c7cd5a4,0x63902bbf,0xda8cbac5
};

int main()
{
    volatile int *p;
    int i;
    u_int32 Re_Data;

    printf("Begin to Reset SM3 Core .....\n");
    // Write Data to Control Reg0,Reset SM4 Core
    p = NULL;
    if(Write_Ctr(p,0,SM3_Reset_Cmd))  printf("SM3 Core Reset Successful!\n");
    else {
        printf("SM3 Core Reset Failed!\n");
        return -1;
    }
    // Write Control Reg1,Inject SM3's length 
    if(Write_Ctr(p,1,SM3_Length))  printf("SM3 length Register 1 Inject Successful!\n");
    // Write Control Reg2,Inject SM3's length 
    if(Write_Ctr(p,2,0))  printf("SM3 length Register 2 Inject Successful!\n"); 
    // Write Control Reg0,the last data's length is 4 bytes
    if(Write_Ctr(p,0,SM3_Dnt_4_Cmd))  printf("SM3 Control Reg 0 Inject Successful!\n"); 
    // Inject Data
    Write_Data(p,SM3_Plain_Data,sizeof(SM3_Plain_Data)/4);
    
    // Read SM3 Core Output Data
    for(i=0;i<8;i++)
    {
        Re_Data = Read_Data_Single(p,SM3_Data_Addr);
        if(Re_Data != SM3_True_Result[i])
            printf("SM3 Test Failed!\n");
    }
    printf("SM3 Test Succeed!\n");
    
    // free the pointer
    free(p);
    p = NULL;

    return 0;
}


/*-----------------------------------------*/
/*    Write Ecc Core's control register    */
/*    Address :0 => ControlReg0            */
/*             1 => ControlReg1            */
/*             2 => ControlReg2            */
/*-----------------------------------------*/
u_int8 Write_Ctr(volatile int *p, u_int8 Address, u_int32 Data)
{
    if(Address == 0)  
    {
        p = (int *)CR0_Addr;
        *p = Data;
        return 1;
    }
    else if(Address == 1)
    {
        p = (int *)CR1_Addr;
        *p = Data;
        return 1;
    }    
    else if(Address == 2)
    {
        p = (int *)CR2_Addr;
        *p = Data;
        return 1;
    }
    return 0;
}


/*-----------------------------------------*/
/* Write Ecc Core's data fifo for one time */
/*-----------------------------------------*/
void Write_Data_Single(volatile int *p, u_int32 Data)
{
    p = (int *)Data_Addr;
    *p = Data;
}

/*------------------------------------------*/
/* Write Ecc Core's data fifo for num times */
/*     The Data array's size must be num    */ 
/*------------------------------------------*/
void Write_Data(volatile int *p, u_int32 Data[], int num)
{
    int i;
    p = (int *)Data_Addr;
    for(i=0;i<num;i++)
    {
        *p = Data[i];
    }
}

/*-------------------------------------------*/
/* Write Ecc Core's output data for one time */
/*-------------------------------------------*/
u_int32 Read_Data_Single(volatile int *p, u_int32 ReadAddr)
{
    p = (int *)ReadAddr;
    return *p;
}

软件调试

进入pulpino/sw文件夹,在当前目录下建立bulid文件夹,拷贝cmake_configure.micror -iscy.gcc.sh、cmake_configure.riscv.gcc.sh、cmake_configure.riscvfloat.gcc.sh、cmake_configure. zeroriscy. gcc.sh其中一个文件到bulid文件夹中,进入bulid文件夹,例如拷贝的为cmake_configure.riscv.gcc.sh文件,终端中运行如下的命令:./cmake_configure.riscv.gcc.sh,等待文件生成(前提是riscv的编译链已将编译成功,并且riscv的gcc环境变量已经添加)。而后依次运行:make helloworld、make vcompile分别编译c文件得到二进制文件,编译全部的硬件代码(包含自定义IP), 编译分别如下所示:

make helloworld

在这里插入图片描述

make vcompile

在这里插入图片描述
编译成功后运行:

make helloworld.vsimc

进行控制台运行程序模式,如下所示:
在这里插入图片描述

硬件调试

为了检查总线上是否有数据进行传输,运行如下命令对仿真波形进行查看:

make helloworld.vsim

如下图所示:
在这里插入图片描述
波形调试如下:
在这里插入图片描述
至此,AXI接口自定义IP成功挂载到Pulpino SoC上,并完成了数据的传输。

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小陈的芯片学习之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值