基于 AXI-Lite 实现可扩展的硬件函数 RPC 框架(附完整源码)

发布于:2025-08-02 ⋅ 阅读:(24) ⋅ 点赞:(0)

AXI-Lite 实现RPC调用硬件函数服务

👋 本文介绍如何基于 AXI-Lite 总线设计一个通用的“硬件函数调用框架”。主机端(PS)只需通过寄存器写入参数与启动标志,即可触发 PL 模块执行指定算法逻辑,并将结果返回。

该机制本质上是一种硬件层的远程过程调用(RPC),在嵌入式/FPGA 系统中具有广泛应用价值,特别适用于:

  • 💡 自定义算法逻辑(如加法、乘法、查表)
  • ⚡ 硬件加速模块(如滤波、压缩、比对)
  • 🧱 基于寄存器映射的服务型模块自定义外设

AXI-Lite的原理和使用可参考我的另一篇文章:

👉 《Zynq AXI-Lite 总线原理与实现》


BD图

在这里插入图片描述


📦 系统结构

     ┌──────────────┐
     │   PS 主机    │
     │  (ARM/Linux) │
     └──────┬───────┘
            │AXI-Lite
     ┌──────▼───────┐
     │ axi_lite_slave │ ← 提供寄存器读写接口
     └──────┬───────┘
            │
     ┌──────▼──────────┐
     │  rpc_processor │ ← 执行“函数”调用(如加法)
     └────────────────┘

🧠 功能简介

  • ✅ PS 主机通过 AXI-Lite 写入参数、选择方法、触发执行
  • ✅ PL 模块 rpc_processor 根据方法编号执行对应处理(如参数加法)
  • ✅ 支持多个返回值(最多 4 个)
  • ✅ 通过仿真 testbench + PS 代码两种方式调用与验证

📐 寄存器定义

地址偏移 名称 作用 位说明
0x00 REG_CTRL 控制与状态寄存器 [0]=start,[1]=ready,[2]=done,[3]=valid
0x04 REG_METHOD 方法编号(功能码) 0 = 回显(ECHO),1 = 加法(ADD)
0x08~0x14 REG_ARG0~3 输入参数(共4个) 32-bit 输入
0x18~0x24 REG_RES0~3 输出结果(共4个) 32-bit 输出

📌 所有寄存器均为 32-bit,支持通过 AXI-Lite 接口进行读写访问。


寄存器映射表

mem索引 地址偏移 寄存器名称 说明
mem[0] 0x00 REG_CTRL 控制/状态
mem[1] 0x04 REG_METHOD 方法编号
mem[2] 0x08 REG_ARG0 请求参数0
mem[3] 0x0C REG_ARG1 请求参数1
mem[4] 0x10 REG_ARG2 请求参数2
mem[5] 0x14 REG_ARG3 请求参数3
mem[6] 0x18 REG_RES0 响应结果0
mem[7] 0x1C REG_RES1 响应结果1
mem[8] 0x20 REG_RES2 响应结果2
mem[9] 0x24 REG_RES3 响应结果3

rpc_processor.v

`timescale 1ns/1ps

// 宏定义:RPC方法(32位功能码)
`define RPC_FUNC_ECHO    32'h00000000  // 回显功能(返回输入参数)
`define RPC_FUNC_ADD     32'h00000001  // 加法功能(参数相加)

module rpc_processor (
    input  wire        i_clk,         // 时钟信号
    input  wire        i_rst_n,       // 复位信号(低有效)

    // 寄存器接口(直接暴露)
    input  wire [31:0] i_method_reg,  // 方法选择寄存器
    input  wire [31:0] i_req_reg_0,   // 请求参数0
    input  wire [31:0] i_req_reg_1,   // 请求参数1
    input  wire [31:0] i_req_reg_2,   // 请求参数2
    input  wire [31:0] i_req_reg_3,   // 请求参数3
    output reg  [31:0] o_res_reg_0,   // 响应结果0
    output reg  [31:0] o_res_reg_1,   // 响应结果1
    output reg  [31:0] o_res_reg_2,   // 响应结果2
    output reg  [31:0] o_res_reg_3,   // 响应结果3

    // RPC控制信号(含启动信号)
    input  wire        i_rpc_start,   // RPC启动信号(1=触发处理,上升沿有效)
    output reg         o_rpc_valid,   // RPC请求有效(处理中保持高)
    input  wire        i_rpc_ready,   // 外部处理就绪(1=可接收请求)
    output reg         o_rpc_done     // RPC处理完成(1=结果有效)
);

    // --------------------------
    // 启动信号边沿检测(防止持续触发)
    // --------------------------
    reg r_rpc_start_dly;
    wire w_rpc_start_posedge;  // 启动信号上升沿(真正的触发点)

    always @(posedge i_clk or negedge i_rst_n) begin
        if (!i_rst_n) begin
            r_rpc_start_dly <= 1'b0;
        end else begin
            r_rpc_start_dly <= i_rpc_start;  // 延迟一拍用于边沿检测
        end
    end

    assign w_rpc_start_posedge = i_rpc_start && !r_rpc_start_dly;  // 上升沿检测

    // --------------------------
    // 内部锁存寄存器(处理期间保持参数稳定)
    // --------------------------
    reg [31:0] r_method_latch;
    reg [31:0] r_req_latch_0, r_req_latch_1, r_req_latch_2, r_req_latch_3;

    // --------------------------
    // RPC处理状态机
    // --------------------------
    localparam S_IDLE      = 2'b00;
    localparam S_PROCESSING = 2'b01;
    localparam S_DONE      = 2'b10;

    reg [1:0] r_state;
    reg [3:0] r_proc_cnt;  // 模拟处理延迟(0~15周期)

    always @(posedge i_clk or negedge i_rst_n) begin
        if (!i_rst_n) begin
            r_state <= S_IDLE;
            r_proc_cnt <= 4'h0;
            o_rpc_valid <= 1'b0;
            o_rpc_done <= 1'b0;
            r_method_latch <= 32'h0;
            r_req_latch_0 <= 32'h0;
            r_req_latch_1 <= 32'h0;
            r_req_latch_2 <= 32'h0;
            r_req_latch_3 <= 32'h0;
            o_res_reg_0 <= 32'h0;
            o_res_reg_1 <= 32'h0;
            o_res_reg_2 <= 32'h0;
            o_res_reg_3 <= 32'h0;
        end else begin
            case (r_state)
                S_IDLE: begin
                    // 检测到启动信号上升沿,且外部就绪时,启动处理
                    if (w_rpc_start_posedge && i_rpc_ready) begin
                        o_rpc_done <= 1'b0;  // 完成标志清0
                        // 锁存当前寄存器值(处理期间参数不变)
                        r_method_latch <= i_method_reg;
                        r_req_latch_0 <= i_req_reg_0;
                        r_req_latch_1 <= i_req_reg_1;
                        r_req_latch_2 <= i_req_reg_2;
                        r_req_latch_3 <= i_req_reg_3;

                        o_rpc_valid <= 1'b1;      // 置位请求有效
                        r_state <= S_PROCESSING;    // 进入处理状态
                        r_proc_cnt <= 4'h0;       // 重置延迟计数器
                    end else begin
                        o_rpc_valid <= 1'b0;
                        r_state <= S_IDLE;
                    end
                end

                S_PROCESSING: begin
                    // 模拟处理延迟(例如10个时钟周期,可修改)
                    if (r_proc_cnt >= 4'd9) begin
                        // 根据方法号执行不同处理(示例逻辑)
                        case (r_method_latch)
                            `RPC_FUNC_ECHO: begin  // 方法0:返回请求参数
                                o_res_reg_0 <= r_req_latch_0;
                                o_res_reg_1 <= r_req_latch_1;
                                o_res_reg_2 <= r_req_latch_2;
                                o_res_reg_3 <= r_req_latch_3;
                            end
                            `RPC_FUNC_ADD: begin  // 方法1:参数相加
                                o_res_reg_0 <= r_req_latch_0 + r_req_latch_1;
                                o_res_reg_1 <= r_req_latch_2 + r_req_latch_3;
                                o_res_reg_2 <= r_req_latch_0 + r_req_latch_2;
                                o_res_reg_3 <= r_req_latch_1 + r_req_latch_3;
                            end
                            default: begin  
                                o_res_reg_0 <= 32'h0;
                                o_res_reg_1 <= 32'h0;
                                o_res_reg_2 <= 32'h0;
                                o_res_reg_3 <= 32'h0;
                            end
                        endcase
                        r_state <= S_DONE;
                    end else begin
                        r_proc_cnt <= r_proc_cnt + 1'b1;
                        r_state <= S_PROCESSING;
                    end
                end

                S_DONE: begin
                    o_rpc_valid <= 1'b0;      // 清除请求有效
                    o_rpc_done <= 1'b1;       // 置位完成标志(通知结果就绪)
                    r_state <= S_IDLE;          // 返回空闲状态,等待下一次启动
                end

                default: r_state <= S_IDLE;
            endcase
        end
    end

endmodule

tb_rpc_processor.sv

`timescale 1ns/1ps

// 接口定义:抽象DUT的所有信号
interface rpc_if;
    logic         i_clk;
    logic         i_rst_n;
    logic [31:0]  i_method_reg;
    logic [31:0]  i_req_reg_0;
    logic [31:0]  i_req_reg_1;
    logic [31:0]  i_req_reg_2;
    logic [31:0]  i_req_reg_3;
    logic         i_rpc_start;
    logic         i_rpc_ready;
    logic [31:0]  o_res_reg_0;
    logic [31:0]  o_res_reg_1;
    logic [31:0]  o_res_reg_2;
    logic [31:0]  o_res_reg_3;
    logic         o_rpc_valid;
    logic         o_rpc_done;

    // 时钟生成(50MHz,周期20ns)
    initial begin
        i_clk = 1'b0;
        forever #10 i_clk = ~i_clk;
    end
endinterface

// RPC测试类:封装所有测试逻辑
class rpc_tester;
    // 虚拟接口:用于连接DUT
    virtual rpc_if vif;
    
    // 宏定义:RPC方法(与DUT保持一致)
    localparam RPC_FUNC_ECHO = 32'h00000000;
    localparam RPC_FUNC_ADD  = 32'h00000001;

    // 构造函数:绑定接口
    function new(virtual rpc_if ifc);
        vif = ifc;
    endfunction

    // 初始化所有信号
    task initialize();
        vif.i_rst_n = 1'b0;
        vif.i_method_reg = 32'h0;
        vif.i_req_reg_0 = 32'h0;
        vif.i_req_reg_1 = 32'h0;
        vif.i_req_reg_2 = 32'h0;
        vif.i_req_reg_3 = 32'h0;
        vif.i_rpc_start = 1'b0;
        vif.i_rpc_ready = 1'b0;
    endtask

    // 执行复位并等待稳定
    task reset();
        @(posedge vif.i_clk);
        vif.i_rst_n = 1'b0;
        #100;  // 保持复位100ns
        @(posedge vif.i_clk);
        vif.i_rst_n = 1'b1;  // 释放复位
        #20;   // 等待复位释放稳定
    endtask

    // 发送RPC请求并等待完成
    task send_rpc(
        input logic [31:0] method,
        input logic [31:0] req0,
        input logic [31:0] req1,
        input logic [31:0] req2,
        input logic [31:0] req3,
        input logic        ready
    );
        // 设置请求参数
        @(posedge vif.i_clk);
        vif.i_method_reg = method;
        vif.i_req_reg_0 = req0;
        vif.i_req_reg_1 = req1;
        vif.i_req_reg_2 = req2;
        vif.i_req_reg_3 = req3;
        vif.i_rpc_ready = ready;

        // 产生start上升沿
        @(posedge vif.i_clk);
        vif.i_rpc_start = 1'b1;
        @(posedge vif.i_clk);
        vif.i_rpc_start = 1'b0;

        // 等待处理完成(如果ready为1)
        if (ready) begin
            wait(vif.o_rpc_done == 1'b1);
            @(posedge vif.i_clk);
        end
    endtask

    // 验证ADD方法结果
    task verify_add_result(
        input logic [31:0] exp0,
        input logic [31:0] exp1,
        input logic [31:0] exp2,
        input logic [31:0] exp3
    );
        @(posedge vif.i_clk);
        if (vif.o_res_reg_0 == exp0 && vif.o_res_reg_1 == exp1 &&
            vif.o_res_reg_2 == exp2 && vif.o_res_reg_3 == exp3) begin
            $display("ADD method test passed %d",exp0);
        end else begin
            $display("ADD method test failed, Expected: %h %h %h %h, Actual: %h %h %h %h",
                     exp0, exp1, exp2, exp3,
                     vif.o_res_reg_0, vif.o_res_reg_1, vif.o_res_reg_2, vif.o_res_reg_3);
        end
    endtask

    // 运行完整测试序列
    task run_test();
        // 初始化并复位
        initialize();
        reset();

        // 执行ADD方法测试
        send_rpc(
            RPC_FUNC_ADD,
            32'h00000001,  // req0
            32'h00000002,  // req1
            32'h00000003,  // req2
            32'h00000004,  // req3
            1'b1           // ready
        );

        // 验证结果(1+2=3, 3+4=7, 1+3=4, 2+4=6)
        verify_add_result(
            32'h00000003,
            32'h00000007,
            32'h00000004,
            32'h00000006
        );


           // 执行ADD方法测试
        send_rpc(
            RPC_FUNC_ADD,
            32'h00000001,  // req0
            32'h00000002,  // req1
            32'h00000003,  // req2
            32'h00000004,  // req3
            1'b1           // ready
        );

        // 验证结果(1+2=3, 3+4=7, 1+3=4, 2+4=6)
        verify_add_result(
            32'h00000003,
            32'h00000007,
            32'h00000004,
            32'h00000006
        );

        // 测试完成
        #100;
        $display("All tests completed");
        $finish;
    endtask
endclass

// 顶层测试平台
module tb;

    wire w_test;
    // 实例化接口
    rpc_if rpc_ifc();

    // 实例化DUT并连接接口
    rpc_processor uut (
        .i_clk         (rpc_ifc.i_clk),
        .i_rst_n       (rpc_ifc.i_rst_n),
        .i_method_reg  (rpc_ifc.i_method_reg),
        .i_req_reg_0   (rpc_ifc.i_req_reg_0),
        .i_req_reg_1   (rpc_ifc.i_req_reg_1),
        .i_req_reg_2   (rpc_ifc.i_req_reg_2),
        .i_req_reg_3   (rpc_ifc.i_req_reg_3),
        .o_res_reg_0   (rpc_ifc.o_res_reg_0),
        .o_res_reg_1   (rpc_ifc.o_res_reg_1),
        .o_res_reg_2   (rpc_ifc.o_res_reg_2),
        .o_res_reg_3   (rpc_ifc.o_res_reg_3),
        .i_rpc_start   (rpc_ifc.i_rpc_start),
        .o_rpc_valid   (rpc_ifc.o_rpc_valid),
        .i_rpc_ready   (rpc_ifc.i_rpc_ready),
        .o_rpc_done    (rpc_ifc.o_rpc_done)
    );

    // 启动测试
    initial begin
        // 创建测试实例并运行测试
        rpc_tester tester = new(rpc_ifc);
        tester.run_test();
    end
endmodule


axi_lite_slave.v

module axi_lite_slave #(
    parameter ADDR_WIDTH = 32,             // 地址总线位宽 Address width
    parameter DATA_WIDTH = 32,             // 数据总线位宽 Data width
    parameter MEM_SIZE   = 1024            // 内部存储器大小(单位:字节) Memory size in bytes
)(
    input  wire                     clk,           // 时钟 Clock
    input  wire                     rst_n,         // 异步复位,低有效 Asynchronous reset, active-low

    // AXI 写地址通道(Write Address Channel)
    input  wire [ADDR_WIDTH-1:0]    s_axi_awaddr,  // 写地址 Write address
    input  wire                     s_axi_awvalid, // 写地址有效 Write address valid
    output reg                      s_axi_awready, // 写地址就绪 Write address ready

    // AXI 写数据通道(Write Data Channel)
    input  wire [DATA_WIDTH-1:0]    s_axi_wdata,   // 写数据 Write data
    input  wire [(DATA_WIDTH/8)-1:0] s_axi_wstrb,  // 写字节使能 Byte enable
    input  wire                     s_axi_wvalid,  // 写数据有效 Write data valid
    output reg                      s_axi_wready,  // 写数据就绪 Write data ready

    // AXI 写响应通道(Write Response Channel)
    output reg  [1:0]               s_axi_bresp,   // 写响应 Write response
    output reg                      s_axi_bvalid,  // 写响应有效 Write response valid
    input  wire                     s_axi_bready,  // 写响应就绪 Write response ready

    // AXI 读地址通道(Read Address Channel)
    input  wire [ADDR_WIDTH-1:0]    s_axi_araddr,  // 读地址 Read address
    input  wire                     s_axi_arvalid, // 读地址有效 Read address valid
    output reg                      s_axi_arready, // 读地址就绪 Read address ready

    // AXI 读数据通道(Read Data Channel)
    output reg  [DATA_WIDTH-1:0]    s_axi_rdata,   // 读数据 Read data
    output reg  [1:0]               s_axi_rresp,   // 读响应 Read response
    output reg                      s_axi_rvalid,  // 读数据有效 Read data valid
    input  wire                     s_axi_rready   // 读数据就绪 Read data ready
);

    // 内部寄存器(寄存器文件,32-bit对齐)
    reg [DATA_WIDTH-1:0] mem [0:(MEM_SIZE/DATA_WIDTH)-1];

    // RPC 处理器输出端口连接线
    wire [31:0] w_res_reg_0, w_res_reg_1, w_res_reg_2, w_res_reg_3;
    wire        w_rpc_done, w_rpc_valid;

    // 状态定义(State definitions)
    localparam IDLE        = 3'd0;
    localparam WRITE_ADDR  = 3'd1;
    localparam WRITE_DATA  = 3'd2;
    localparam WRITE_RESP  = 3'd3;
    localparam READ_ADDR   = 3'd4;
    localparam READ_DATA   = 3'd5;

    reg [2:0] state, next_state;              // 状态寄存器
    reg [ADDR_WIDTH-1:0] write_addr;         // 写地址寄存器
    reg [ADDR_WIDTH-1:0] read_addr;          // 读地址寄存器

    // 状态机:状态跳转逻辑
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            state <= IDLE;
        else
            state <= next_state;
    end

    // 状态机:下一状态逻辑
    always @(*) begin
        next_state = state;
        case (state)
            IDLE: begin
                if (s_axi_awvalid)
                    next_state = WRITE_ADDR;
                else if (s_axi_arvalid)
                    next_state = READ_ADDR;
            end
            WRITE_ADDR: next_state = WRITE_DATA;
            WRITE_DATA: if (s_axi_wvalid) next_state = WRITE_RESP;
            WRITE_RESP: if (s_axi_bready) next_state = IDLE;
            READ_ADDR : next_state = READ_DATA;
            READ_DATA : if (s_axi_rready) next_state = IDLE;
            default   : next_state = IDLE;
        endcase
    end

    // 输出逻辑:AXI 信号 + 寄存器读写
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // 所有输出复位
            s_axi_awready <= 0;
            s_axi_wready  <= 0;
            s_axi_bresp   <= 0;
            s_axi_bvalid  <= 0;
            s_axi_arready <= 0;
            s_axi_rdata   <= 0;
            s_axi_rresp   <= 0;
            s_axi_rvalid  <= 0;
            write_addr    <= 0;
            read_addr     <= 0;
            //mem 初始化
            mem[0][0] <= 1'b0;
            mem[0][2] <= 1'b0;
            mem[0][3] <= 1'b0;
            mem[6]    <= 32'd0;
            mem[7]    <= 32'd0;
            mem[8]    <= 32'd0;
            mem[9]    <= 32'd0;
            // 模块重编译生效测试
            mem[20]   <= 7624;
        end else begin
            case (state)
                IDLE: begin
                    // 清除所有 ready/valid 信号
                    s_axi_awready <= 0;
                    s_axi_wready  <= 0;
                    s_axi_bvalid  <= 0;
                    s_axi_arready <= 0;
                    s_axi_rvalid  <= 0;
                    // 接收写地址或读地址
                    if (s_axi_awvalid) begin
                        s_axi_awready <= 1;
                        write_addr    <= s_axi_awaddr;
                    end else if (s_axi_arvalid) begin
                        s_axi_arready <= 1;
                        read_addr     <= s_axi_araddr;
                    end
                end
                WRITE_ADDR: begin
                    s_axi_awready <= 0;
                    s_axi_wready  <= 1;   // 等待写数据
                end
                WRITE_DATA: begin
                    if (s_axi_wvalid) begin
                        s_axi_wready <= 0;
                        mem[write_addr[8:2]] <= s_axi_wdata;  // 写入数据
                        s_axi_bresp  <= 2'b00;                // OKAY
                        s_axi_bvalid <= 1;
                    end
                end
                WRITE_RESP: begin
                    if (s_axi_bready)
                        s_axi_bvalid <= 0;
                end
                READ_ADDR: begin
                    s_axi_arready <= 0;
                    s_axi_rdata   <= mem[read_addr[8:2]];     // 读取数据
                    s_axi_rresp   <= 2'b00;                   // OKAY
                    s_axi_rvalid  <= 1;
                end
                READ_DATA: begin
                    if (s_axi_rready)
                        s_axi_rvalid <= 0;
                end
            endcase

            // 每个时钟周期更新 RPC 输出值到寄存器(6~9)
            mem[6] <= w_res_reg_0;
            mem[7] <= w_res_reg_1;
            mem[8] <= w_res_reg_2;
            mem[9] <= w_res_reg_3;
            mem[0][2] <= w_rpc_done;
            mem[0][3] <= w_rpc_valid;
        end
    end

    // 实例化 RPC 处理器模块,连接输入参数和输出结果寄存器
    rpc_processor u_rpc (
        .i_clk        (clk),
        .i_rst_n      (rst_n),
        .i_method_reg (mem[1]),        // 功能号寄存器
        .i_req_reg_0  (mem[2]),        // 参数0
        .i_req_reg_1  (mem[3]),        // 参数1
        .i_req_reg_2  (mem[4]),        // 参数2
        .i_req_reg_3  (mem[5]),        // 参数3
        .o_res_reg_0  (w_res_reg_0),   // 返回值0
        .o_res_reg_1  (w_res_reg_1),   // 返回值1
        .o_res_reg_2  (w_res_reg_2),   // 返回值2
        .o_res_reg_3  (w_res_reg_3),   // 返回值3
        .i_rpc_start  (mem[0][0]),     // 启动标志
        .i_rpc_ready  (mem[0][1]),     // RPC主机方法和参数准备好了
        .o_rpc_done   (w_rpc_done),    // RPC处理完成(1=结果有效)
        .o_rpc_valid  (w_rpc_valid)    // RPC请求有效(处理中保持高)
    );

endmodule

PS 裸机测试

#include "xil_io.h"
#include "xil_printf.h"
#include <stdio.h>

#define BASE_ADDR       0x43c00000
#define MAX_INDEX   30
#define REG_CTRL        (BASE_ADDR + 4*0)
#define REG_METHOD      (BASE_ADDR + 4*1)
#define REG_ARG0        (BASE_ADDR + 4*2)
#define REG_ARG1        (BASE_ADDR + 4*3)
#define REG_ARG2        (BASE_ADDR + 4*4)
#define REG_ARG3        (BASE_ADDR + 4*5)
#define REG_RES0        (BASE_ADDR + 4*6)
#define REG_RES1        (BASE_ADDR + 4*7)
#define REG_RES2        (BASE_ADDR + 4*8)
#define REG_RES3        (BASE_ADDR + 4*9)

#define BIT_RPC_START   (1 << 0)
#define BIT_RPC_READY   (1 << 1)
#define BIT_RPC_DONE    (1 << 2)
#define BIT_RPC_VALID   (1 << 3)

void rpc_call(u32 method, u32 a0, u32 a1, u32 a2, u32 a3) {
    Xil_Out32(REG_METHOD, method);
    Xil_Out32(REG_ARG0, a0);
    Xil_Out32(REG_ARG1, a1);
    Xil_Out32(REG_ARG2, a2);
    Xil_Out32(REG_ARG3, a3);
    Xil_Out32(REG_CTRL, BIT_RPC_READY | BIT_RPC_START);
    int timeout_cnt = 0;
    const int TIMEOUT_MAX = 100;
    while (Xil_In32(REG_CTRL) & BIT_RPC_DONE == 0) {
        if (++timeout_cnt > TIMEOUT_MAX) {
            xil_printf("Timeout: RPC method %d failed.\n", method);
            Xil_Out32(REG_CTRL, 0x00);
            return;
        }
    }
    Xil_Out32(REG_CTRL, 0x00);
    u32 r0 = Xil_In32(REG_RES0);
    u32 r1 = Xil_In32(REG_RES1);
    u32 r2 = Xil_In32(REG_RES2);
    u32 r3 = Xil_In32(REG_RES3);
    xil_printf("RPC method %d result:\n", method);
    xil_printf("  res0 : %d=%d+%d\n", r0,a0,a1);
    xil_printf("  res1 : %d=%d+%d\n", r1,a2,a3);
    xil_printf("  res2 : %d=%d+%d\n", r2,a0,a2);
    xil_printf("  res3 : %d=%d+%d\n", r3,a1,a3);
}


void dump_registers() {
    u32 val;

    xil_printf("AXI Register Dump (HEX + DEC):\n");

    val = Xil_In32(REG_CTRL);
    xil_printf("  mem[0]  REG_CTRL   = 0x%08X  (%10u)\n", val, val);

    val = Xil_In32(REG_METHOD);
    xil_printf("  mem[1]  REG_METHOD = 0x%08X  (%10u)\n", val, val);

    val = Xil_In32(REG_ARG0);
    xil_printf("  mem[2]  REG_ARG0   = 0x%08X  (%10u)\n", val, val);

    val = Xil_In32(REG_ARG1);
    xil_printf("  mem[3]  REG_ARG1   = 0x%08X  (%10u)\n", val, val);

    val = Xil_In32(REG_ARG2);
    xil_printf("  mem[4]  REG_ARG2   = 0x%08X  (%10u)\n", val, val);

    val = Xil_In32(REG_ARG3);
    xil_printf("  mem[5]  REG_ARG3   = 0x%08X  (%10u)\n", val, val);

    val = Xil_In32(REG_RES0);
    xil_printf("  mem[6]  REG_RES0   = 0x%08X  (%10u)\n", val, val);

    val = Xil_In32(REG_RES1);
    xil_printf("  mem[7]  REG_RES1   = 0x%08X  (%10u)\n", val, val);

    val = Xil_In32(REG_RES2);
    xil_printf("  mem[8]  REG_RES2   = 0x%08X  (%10u)\n", val, val);

    val = Xil_In32(REG_RES3);
    xil_printf("  mem[9]  REG_RES3   = 0x%08X  (%10u)\n", val, val);
}


int main() {
    xil_printf("AXI RPC Test Console. Type 't' and press Enter to test.\n");

    char cmd;
    int index;
    u32 value;
    static int p=0;

    while (1) {
        xil_printf("> ");
        if (scanf(" %c", &cmd) != 1)
            continue;

        if (cmd == 't' || cmd == 'T') {

            rpc_call(1, 1, 2, 3, 4);

            rpc_call(1, 10, 20, 30, 40);

            continue;
        }

        switch (cmd)
                {
                    case 'r':
                        if (scanf("%d", &index) == 1)
                        {
                            if (index < 0 || index > MAX_INDEX)
                            {
                                xil_printf("Error: index out of range [0 ~ %d]\r\n", MAX_INDEX);
                                while (getchar() != '\n');
                                continue;
                            }

                            u32 read_val = Xil_In32(BASE_ADDR + 4 * index);
                            xil_printf("[r %d] = 0x%08X / %u\r\n", index, read_val, read_val);
                        }
                        else
                        {
                            xil_printf("Invalid input. Use: r <index>\r\n");
                            while (getchar() != '\n');
                        }
                        break;

                    case 'w':
                        if (scanf("%d %u", &index, &value) == 2)
                        {
                            if (index < 0 || index > MAX_INDEX)
                            {
                                xil_printf("Error: index out of range [0 ~ %d]\r\n", MAX_INDEX);
                                while (getchar() != '\n');
                                continue;
                            }

                            Xil_Out32(BASE_ADDR + 4 * index, value);
                            xil_printf("[w %d] = 0x%08X / %u\r\n", index, value, value);
                        }
                        else
                        {
                            xil_printf("Invalid input. Use: w <index> <value>\r\n");
                            while (getchar() != '\n');
                        }
                        break;
                    case 'l':{
                    	dump_registers();
                    	break;
                    }
                    default:
                        xil_printf("Unknown command '%c'. Use 'r' or 'w'.\r\n", cmd);
                        while (getchar() != '\n');
                        break;
                }
    }

    return 0;
}

测试结果

[16:27:01.812]发→◇t
□
[16:27:01.815]收←◆RPC method 1 result:
  res0 : 3=1+2
  res1 : 7=3+4
  res2 : 4=1+3
  res3 : 6=2+4
RPC method 1 result:
  res0 : 30=10+20
  res1 : 70=30+40
  res2 : 40=10+30
  res3 : 60=20+40
>