1070|1

842

帖子

3

TA的资源

版主

楼主
 

4、【国产FPGA安路 高集成低功耗SF1系列FPSoC新品测评】MCU通过AHB总线访问FPGA [复制链接]

 
SF1 是集成了三级流水线的 RISC-V MCU 内核以及包含有 5824 LUTs 的 FPGA。RISC-V MCU 预留 AHB端口,可通过 AHB 总线访问 FPGA 用户逻辑,也可访问 PSRAM 等存储单元。所以这次来看下MCU通过AHB访问FPGA的功能,MCU访问FPGA时MCU为master端,FPGA为slave端。
设计框图如下图所示,ahb_to_register 模块是 fpga 侧 ahb 总线读写寄存器模块,用户可以通过这个模块自定义输入输出寄存器,CPU 通过 ahb 总线连接到 ahb_to_register 模块,以此来访问 fpga侧的数据。在本例程中,ahb_to_register 模块定义了一个 32 位 fpga 版本号端口,一个 1 位 led 控制端口,CPU 通过 ahb 总线读取 fpga 版本号并通过串口打印出来,同时通过 ahb 总线控制 fpga 侧的 io, 以此来点亮一个 led 灯。其中FPGA侧是AHB slave。

ahb_to_register模块

fpga 侧的 ahb_to_register ,自定义了两个端口,fpga 版本号 I_pl_version和 led 控制端口 O_pl_led。fpga 版本号设定为 22060901,led 控制端口直接输出到 io 上。其余端口为ahb总线端口,这些端口在FPGA中实现AHB slave接收MCU发送的数据等信息。
ahb 总线的起始地址是 0x40000000,在 ahb_to_register 模块中 I_pl_version 和 O_pl_led 的偏移地址分别是 0x0 和 0x4,因此在 c 代码中先设定两个端口的地址,如下图所示。ahb总线的地址信息没有在《TN817_SF1 MCU用户指南》文档中找到,而是在《TN810_SF102开发板应用例程使用指南》文档中的例程介绍中稍微提到了一下,建议在《TN817_SF1 MCU用户指南》标出毕竟该总线是MCU访问FPGA需要用到的,该文档中0x40000000对应的地址写的是System bus,除此之外通篇没有该地址的具体描述。
关于AHB总线:
    AHB总线接口有以下信号,在本例程中除了HSELx没有用到之外其余接口都有使用到,HSELx信号是在多个ahb总线的系统中使用的,用于选中需要的ahb总线。HCLK为ahb总线时钟,HRESETn为总线的复位,HADDR为总线的地址信号位宽为32位,HTRANS为总线的传输模式分为NONSEQ、SEQ、IDLE、BUSY四种模式,HSIZE为总线传输的数据大小,HBURST为传输数据的burst类型,HPROT为总线保护控制信号,HWDATA和HRDATA为总线的读写数据信号位宽都为32位,HREADY为slave总线传输状态信号,
 


module ahb_to_register (
    input              I_ahb_clk,
    input              I_rst,

    input   [1:0]      I_ahb_htrans,
    input              I_ahb_hwrite,
    input   [31:0]     I_ahb_haddr,       //synthesis keep
    input   [2:0]      I_ahb_hsize,
    input   [2:0]      I_ahb_hburst,
    input   [3:0]      I_ahb_hprot,
    input              I_ahb_hmastlock,
    input   [31:0]     I_ahb_hwdata,      //synthesis keep
    output  reg [31:0] O_ahb_hrdata,      //synthesis keep
    output  wire[1:0]  O_ahb_hresp,
    output  reg        O_ahb_hready,

    input wire[31:0]   I_pl_version,      ///0x0
    output wire        O_pl_led           ///0x4
);



    reg        S_ahb_wr_trig;
    reg        S_ahb_wr_trig_1d;
    reg[31:0]  S_ahb_wr_addr;
    reg[31:0]  S_ahb_wr_data;

    reg        S_ahb_rd_trig;
    reg        S_ahb_rd_trig_1d;
    reg[31:0]  S_ahb_rd_addr;
    reg[31:0]  S_ahb_rd_data;


    reg[31:0]  S_reg_0;
    reg[31:0]  S_reg_1;
    reg[31:0]  S_reg_2;
    reg[31:0]  S_reg_3;
    reg[31:0]  S_reg_4;
    reg[31:0]  S_reg_5;
    reg[31:0]  S_reg_6;
    reg[31:0]  S_reg_7;
	reg[31:0]  S_reg_8;
	reg[31:0]  S_reg_9;
	reg[31:0]  S_reg_10;


    always @(posedge I_ahb_clk or posedge I_rst) begin
        if(I_rst)
            O_ahb_hready <= 1'b1;
        else
            if(I_ahb_htrans == 2'b10)
                O_ahb_hready <= 1'b0;
            else if(S_ahb_wr_trig_1d || S_ahb_rd_trig_1d)
                O_ahb_hready <= 1'b1;
            else
                O_ahb_hready <= O_ahb_hready;
    end

    
    always @(posedge I_ahb_clk or posedge I_rst) begin
        if(I_rst)
            S_ahb_wr_trig <= 1'b0;
        else
            if(I_ahb_htrans == 2'b10 && I_ahb_hwrite)
                S_ahb_wr_trig <= 1'b1;
            else
                S_ahb_wr_trig <= 1'b0;
    end

    always @(posedge I_ahb_clk) begin
        S_ahb_wr_trig_1d <= S_ahb_wr_trig;
    end

    always @(posedge I_ahb_clk or posedge I_rst) begin
        if(I_rst)
            S_ahb_wr_addr <= 'd0;
        else
            if(S_ahb_wr_trig)
                S_ahb_wr_addr <= I_ahb_haddr;
            else
                S_ahb_wr_addr <= S_ahb_wr_addr;
    end

    always @(posedge I_ahb_clk or posedge I_rst) begin
        if(I_rst)
            S_ahb_wr_data <= 'd0;
        else
            if(S_ahb_wr_trig)
                S_ahb_wr_data <= I_ahb_hwdata;
            else
                S_ahb_wr_data <= S_ahb_wr_data;
    end


    always @(posedge I_ahb_clk or posedge I_rst) begin
        if(I_rst)
            begin
                S_reg_0  <= 'd0;
                S_reg_1  <= 'd0;
                S_reg_2  <= 'd0;
                S_reg_3  <= 'd0;
                S_reg_4  <= 'd0;
                S_reg_5  <= 'd0;
                S_reg_6  <= 'd0;
                S_reg_7  <= 'd0;
				S_reg_8  <= 'd0;
				S_reg_9  <= 'd0;
				S_reg_10 <= 'd0;
            end
        else
            begin
                if(S_ahb_wr_trig_1d)
                    begin
                        case(S_ahb_wr_addr[7:0])
                            8'h00: S_reg_0  <= S_ahb_wr_data;
                            8'h04: S_reg_1  <= S_ahb_wr_data;
                            8'h08: S_reg_2  <= S_ahb_wr_data;
                            8'h0C: S_reg_3  <= S_ahb_wr_data;
                            8'h10: S_reg_4  <= S_ahb_wr_data;
                            8'h14: S_reg_5  <= S_ahb_wr_data;
                            8'h18: S_reg_6  <= S_ahb_wr_data;
                            8'h1C: S_reg_7  <= S_ahb_wr_data;
                            8'h20: S_reg_8  <= S_ahb_wr_data;
                            8'h24: S_reg_9  <= S_ahb_wr_data;
                            8'h28: S_reg_10 <= S_ahb_wr_data;
                        endcase
                    end
                else
                    begin
                        S_reg_0  <= S_reg_0;
                        S_reg_1  <= S_reg_1;
                        S_reg_2  <= S_reg_2;
                        S_reg_3  <= S_reg_3;
                        S_reg_4  <= S_reg_4;
                        S_reg_5  <= S_reg_5;
                        S_reg_6  <= S_reg_6;
                        S_reg_7  <= S_reg_7;
                        S_reg_8  <= S_reg_8 ;
                        S_reg_9  <= S_reg_9 ;
                        S_reg_10 <= S_reg_10;
                    end
            end
    end



    always @(posedge I_ahb_clk or posedge I_rst) begin
        if(I_rst)
            S_ahb_rd_trig <= 1'b0;
        else
            if(I_ahb_htrans == 2'b10 && (!I_ahb_hwrite))
                S_ahb_rd_trig <= 1'b1;
            else
                S_ahb_rd_trig <= 1'b0;
    end

    always @(posedge I_ahb_clk) begin
        S_ahb_rd_trig_1d <= S_ahb_rd_trig;
    end

    always @(posedge I_ahb_clk or posedge I_rst) begin
        if(I_rst)
            S_ahb_rd_addr <= 'd0;
        else
            if(S_ahb_rd_trig)
                S_ahb_rd_addr <= I_ahb_haddr;
            else
                S_ahb_rd_addr <= S_ahb_rd_addr;
    end


    always @(posedge I_ahb_clk or posedge I_rst) begin
        if(I_rst)
            O_ahb_hrdata <= 'd0;
        else
            begin
                if(S_ahb_rd_trig_1d)
                    begin
                        case(S_ahb_rd_addr[7:0])
                            8'h00: O_ahb_hrdata <= I_pl_version;
                            8'h04: O_ahb_hrdata <= S_reg_1;
                            8'h08: O_ahb_hrdata <= S_reg_2;
                            8'h0C: O_ahb_hrdata <= S_reg_3;
                            8'h10: O_ahb_hrdata <= S_reg_4;
                            8'h14: O_ahb_hrdata <= S_reg_5;
                            8'h18: O_ahb_hrdata <= S_reg_6;
                            8'h1C: O_ahb_hrdata <= S_reg_7;
                            8'h20: O_ahb_hrdata <= S_reg_8;
                            8'h24: O_ahb_hrdata <= S_reg_9;
                            8'h28: O_ahb_hrdata <= S_reg_10;
                        endcase
                    end
                else
                    O_ahb_hrdata <= O_ahb_hrdata;
            end
    end


    assign O_pl_led = S_reg_1[0];


endmodule

 

ps_wrapper模块

该模块主要负责调用MCU IP核实现MCU和FPGA之间的互联,以及下载的GTAG接口,与PC通讯的UART等外设接口。
module ps_wrapper (
    input wire        I_clk,
    input wire        I_rst,
	input wire        I_timer_clk,

    input wire        I_jtag_tck,
    output wire       O_jtag_tdo,
    input wire        I_jtag_tms,
    input wire        I_jtag_tdi,

    input wire        I_uart_rx,
    output wire       O_uart_tx,

    output wire       O_spi_cs,
    output wire       O_spi_clk,
    output wire       O_spi_mosi,
    input wire        I_spi_miso,

    output wire[1:0]  O_ahb_htrans,
    output wire       O_ahb_hwrite, 
    output wire[31:0] O_ahb_haddr, 
    output wire[2:0]  O_ahb_hsize, 
    output wire[2:0]  O_ahb_hburst,
    output wire[3:0]  O_ahb_hprot,
    output wire       O_ahb_hmastlock,
    output wire[31:0] O_ahb_hwdata, 
    input  wire       I_ahb_hclk,
    input  wire[31:0] I_ahb_hrdata,
    input  wire[1:0]  I_ahb_hresp,
    input  wire       I_ahb_hready,

    output wire       O_apb_clk,
    input wire[31:0]  I_apb_prdata, 
    output wire[31:0] O_apb_pwdata, 
    output wire[3:0]  O_apb_pstrobe,
    output wire[2:0]  O_apb_pprot,
    output wire       O_apb_penable,
    output wire       O_apb_pwrite,
    input wire        I_apb_pslverr,
    input wire        I_apb_pready,
    output wire[11:0] O_apb_paddr,
    output wire       O_apb_psel0,
    output wire       O_apb_psel1,
    output wire       O_apb_psel2,

    inout wire        IO_gpio_0,
    inout wire        IO_gpio_1,
    inout wire        IO_gpio_2,
    inout wire        IO_gpio_3,
    inout wire        IO_gpio_4,
    inout wire        IO_gpio_5,
    inout wire        IO_gpio_6,
    inout wire        IO_gpio_7
);
    

    wire S_gpio0_out;
    wire S_gpio0_dir;
    wire S_gpio0_in ;
    wire S_gpio1_out;
    wire S_gpio1_dir;
    wire S_gpio1_in ;
    wire S_gpio2_out;
    wire S_gpio2_dir;
    wire S_gpio2_in ;
    wire S_gpio3_out;
    wire S_gpio3_dir;
    wire S_gpio3_in ;    //synthesis keep;
    wire S_gpio4_out;
    wire S_gpio4_dir;
    wire S_gpio4_in ;
    wire S_gpio5_out;
    wire S_gpio5_dir;
    wire S_gpio5_in ;
    wire S_gpio6_out;
    wire S_gpio6_dir;
    wire S_gpio6_in ;
    wire S_gpio7_out;
    wire S_gpio7_dir;
    wire S_gpio7_in ;


    gpio_controler u0_gpio_controler(
        .O_gpio_in  ( S_gpio0_in  ),
        .I_gpio_dir ( S_gpio0_dir ),
        .I_gpio_out ( S_gpio0_out ),

        .IO_gpio    ( IO_gpio_0   )
    );

    gpio_controler u1_gpio_controler(
        .O_gpio_in  ( S_gpio1_in  ),
        .I_gpio_dir ( S_gpio1_dir ),
        .I_gpio_out ( S_gpio1_out ),

        .IO_gpio    ( IO_gpio_1   )
    );

    gpio_controler u2_gpio_controler(
        .O_gpio_in  ( S_gpio2_in  ),
        .I_gpio_dir ( S_gpio2_dir ),
        .I_gpio_out ( S_gpio2_out ),

        .IO_gpio    ( IO_gpio_2   )
    );

    gpio_controler u3_gpio_controler(
        .O_gpio_in  ( S_gpio3_in  ),
        .I_gpio_dir ( S_gpio3_dir ),
        .I_gpio_out ( S_gpio3_out ),

        .IO_gpio    ( IO_gpio_3   )
    );

    gpio_controler u4_gpio_controler(
        .O_gpio_in  ( S_gpio4_in  ),
        .I_gpio_dir ( S_gpio4_dir ),
        .I_gpio_out ( S_gpio4_out ),

        .IO_gpio    ( IO_gpio_4   )
    );

    gpio_controler u5_gpio_controler(
        .O_gpio_in  ( S_gpio5_in  ),
        .I_gpio_dir ( S_gpio5_dir ),
        .I_gpio_out ( S_gpio5_out ),

        .IO_gpio    ( IO_gpio_5   )
    );

    gpio_controler u6_gpio_controler(
        .O_gpio_in  ( S_gpio6_in  ),
        .I_gpio_dir ( S_gpio6_dir ),
        .I_gpio_out ( S_gpio6_out ),

        .IO_gpio    ( IO_gpio_6   )
    );

    gpio_controler u7_gpio_controler(
        .O_gpio_in  ( S_gpio7_in  ),
        .I_gpio_dir ( S_gpio7_dir ),
        .I_gpio_out ( S_gpio7_out ),

        .IO_gpio    ( IO_gpio_7   )
    );


    MCU u_MCU(
        .core_clk         ( I_clk             ),
		.timer_clk        ( I_timer_clk       ),
        .core_reset       ( I_rst             ),
    
        .jtag_tck         ( I_jtag_tck        ),
        .jtag_tdo         ( O_jtag_tdo        ),
        .jtag_tms         ( I_jtag_tms        ),
        .jtag_tdi         ( I_jtag_tdi        ),
    
        .soft_ip_apbm_en  ( 1'b0              ),
        .qspi0cfg1_mode   ( 1'b1              ),
        .qspi0cfg2_mode   ( 1'b1              ),
    
        .apb_clk_down     ( O_apb_clk         ),
        .apb_paddr_down   ( O_apb_paddr       ),
        .apb_penable_down ( O_apb_penable     ),
        .apb_pprot_down   ( O_apb_pprot       ),
        .apb_prdata_down  ( I_apb_prdata      ),
        .apb_pready_down  ( I_apb_pready      ),
        .apb_pslverr_down ( I_apb_pslverr     ),
        .apb_pstrobe_down ( O_apb_pstrobe     ),
        .apb_pwdata_down  ( O_apb_pwdata      ),
        .apb_pwrite_down  ( O_apb_pwrite      ),
        .apb_psel0_down   ( O_apb_psel0       ),
        .apb_psel1_down   ( O_apb_psel1       ),
        .apb_psel2_down   ( O_apb_psel2       ),

        .qspi1_dir        (                   ), 
        .qspi1_ss         ( O_spi_cs          ), 
        .qspi1_clk        ( O_spi_clk         ), 
        .qspi1_mosi       ( O_spi_mosi        ), 
        .qspi1_miso       ( I_spi_miso        ), 
        .qspi1_d1_out     (                   ), 
        .qspi1_d2_out     (                   ), 
        .qspi1_d3_out     (                   ), 
        .qspi1_d0_in      (                   ), 
        .qspi1_d2_in      (                   ), 
        .qspi1_d3_in      (                   ), 


        .uart_tx          ( O_uart_tx         ),
        .uart_rx          ( I_uart_rx         ),
    
        .gpio0_out        ( S_gpio0_out       ),
        .gpio0_dir        ( S_gpio0_dir       ),
        .gpio0_in         ( S_gpio0_in        ),
     
        .gpio1_out        ( S_gpio1_out       ),
        .gpio1_dir        ( S_gpio1_dir       ),
        .gpio1_in         ( S_gpio1_in        ),
     
        .gpio2_out        ( S_gpio2_out       ),
        .gpio2_dir        ( S_gpio2_dir       ),
        .gpio2_in         ( S_gpio2_in        ),
     
        .gpio3_out        ( S_gpio3_out       ),
        .gpio3_dir        ( S_gpio3_dir       ),
        .gpio3_in         ( S_gpio3_in        ),
     
        .gpio4_out        ( S_gpio4_out       ),
        .gpio4_dir        ( S_gpio4_dir       ),
        .gpio4_in         ( S_gpio4_in        ),
     
        .gpio5_out        ( S_gpio5_out       ),
        .gpio5_dir        ( S_gpio5_dir       ),
        .gpio5_in         ( S_gpio5_in        ),
     
        .gpio6_out        ( S_gpio6_out       ),
        .gpio6_dir        ( S_gpio6_dir       ),
        .gpio6_in         ( S_gpio6_in        ),
     
        .gpio7_out        ( S_gpio7_out       ),
        .gpio7_dir        ( S_gpio7_dir       ),
        .gpio7_in         ( S_gpio7_in        ),

        .htrans           ( O_ahb_htrans      ),
        .hwrite           ( O_ahb_hwrite      ),
        .haddr            ( O_ahb_haddr       ),
        .hsize            ( O_ahb_hsize       ),
        .hburst           ( O_ahb_hburst      ),
        .hprot            ( O_ahb_hprot       ),
        .hmastlock        ( O_ahb_hmastlock   ),
        .hwdata           ( O_ahb_hwdata      ),
        .hclk             ( I_ahb_hclk        ),
        .hrdata           ( I_ahb_hrdata      ),
        .hresp            ( I_ahb_hresp       ),
        .hready           ( I_ahb_hready      ),

        .i2c_sda_out      (  ),
        .i2c_sda_sel      (  ),
        .i2c_scl_out      (  ),
        .i2c_scl_sel      (  ),
        .i2c_sda_in       (  ),
        .i2c_scl_in       (  ),
        .nmi              (  ),
        .clic_irq         (  ),
        .sysrstreq        (  )

    );


endmodule

 

gpio_controler模块

该模块实现三态门的结构,io_gpio是FPGA的物理端口,o_gpio_in为FPGA输出到MCU的端口,i_gpio_out为接收MCU输出端口,i_gpio_dir用于控制FPGA的端口作为输入还是输出端口。当i_gpio_dir为1时io_gpio作为输出,FPGA输出信号;当i_gpio_dir为0时io_gpio作输入,此时io_gpio为高阻态,高阻态时能够分压到该IO上输入的所有电压。

module gpio_controler (
    output wire   O_gpio_in,
    input wire    I_gpio_dir,  ///1'b0: input , 1'b1: output
    input wire    I_gpio_out,

    inout wire    IO_gpio
);


    assign IO_gpio = I_gpio_dir ? I_gpio_out : 1'bz;

    assign O_gpio_in = IO_gpio;
    
endmodule

 

PLL模块

PLL模块产生MCU和FPGA所需要的时钟,输入参考时钟为25MHz,S_mcu_core_clk为MCU时钟,S_clk_70m为ahb总线时钟。
实验结果:
    下载代码后可以看到LEDB闪烁,例程中说明的功能还包括串口输出打印FPGA型号,但是文件《TN816_安路科技SF102_DEMO板使用指南》中没有说明串口调试工具的配置情况,使用串口调试助手也没有看到输出响应的型号信息。
ahb

 
 

最新回复

FPGA与MCU通信。结合二者的特长,这设计挺好的。  详情 回复 发表于 2024-3-14 10:08
点赞 关注
 
 

回复
举报

6960

帖子

11

TA的资源

版主

沙发
 
FPGA与MCU通信。结合二者的特长,这设计挺好的。
 
 
 

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

随便看看
查找数据手册?

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
快速回复 返回顶部 返回列表